《JAVA并发编程实战》示例程序第一、二章

程序清单1-1非线程安全的数值序列生成器

import net.jcip.annotations.NotThreadSafe;

@NotThreadSafe
public class UnsafeSequence {
	private int value;
	
	/*返回一个唯一的数值*/
	public int getValue() {
		return value++;		//三个操作:读取,加一,赋值。	多线程并发操作value可能导致步骤被打乱
	}
}

程序清单1-2 线程安全的数值序列生成器

public class Sequence {
	private int value;
	
	/*返回一个唯一的数值*/
	public synchronized int getValue() {	//各个线程串行访问
		return value++;
	}
}

程序清单2-1 一个无状态的Servlet ,各个线程间没有共享状态

@ThreadSafe
public class StatelessFactorizer implements Servlet{
	
	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
		BigInteger i = extractFromRequest(req);
		BigInteger[] factories = factor(i);
		encodeIntoResponse(res,factories);
	}
}

  

程序清单2-3 延迟初始化中的竞态条件(不要这么做)

@NotThreadSafe
public class LazyInitRace {
	
	private ExpensiveObject instance = null;	//竞态条件
	
	public ExpensiveObject getInstance() {
		if(instance == null)
			instance = new ExpensiveObject();
		return new ExpensiveObject();
	}
}
class ExpensiveObject{}

程序清单2-4  使用AtomicLong类型的变量来统计已处理请求的数量

/*servlet的状态就是计数器count的状态,count是线程安全的,所以servlet是线程安全的*/
public class CountingFactorizer implements Servlet {
    private final AtomicLong count = new AtomicLong(0); //原子变量类,实现在数值和对象引用上的原子状态转换
    
    public long getCount() { return count.get(); }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        BigInteger i = extractFromReqest(req);
        BigInteger[] factors = factor(i);
        count.incrementAndGet();
        encodeIntoResponse(res,factors);
    }
}

程序清单2-5 Servlet在没有足够原子性保证的情况下对其最近计算结果进行缓存(不要这么做)

/**
 * 因数分解:
 * 在数学中,因数分解,又称素因数分解,是把一个正整数写成几个约数的乘积。例如,给出45这个数,它可以分解成3×3×5,根据算术基本定理,这样的分解结果应该是独一无二的
 * 
 * 
 * 希望提升Servlet性能,将最近的计算结果缓存起来,当2个连续的请求对相同的数值进行因数分解时,可以直接使用上一次的计算结果.
 * 
 * 原子引用本身是线程安全的,但是业务逻辑中存在竞态条件 : 
 *     lastFactors[0] * lastFactors[1] * .....  = lastNumber; 此条件不被破坏,Servlet才是线程安全的。
 */
public class UnsafeCachingFactorizer implements Servlet {
    //lastNumber、lastFactors本身是线程安全的
    private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>();        //上一次请求的 因数
    private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>();    //上一次请求的 因数分解结果
    
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        BigInteger i = extractFromReqest(req);
        if(i.equals(lastNumber)){
            encodeIntoResponse(res,lastFactors.get());
        } else {
            BigInteger[] factors = factor(i);
            lastNumber.set(i);                //无法保证同时与lastFactors更新,
            lastFactors.set(factors);        //无法保证同时与lastNumber更新
            encodeIntoResponse(res,factors);
        }
    }
}

  

猜你喜欢

转载自www.cnblogs.com/guchunchao/p/10702509.html