/** * 该类无任何属性域,且不包含任何其他类中域的引用 * 即计算中的状态都为临时状态,保存在线程栈中 * 由JMM知线程栈线程私有,仅由当前线程可访问 * 因此线程安全 */ @ThreadSafe public class StatelessFactorizer implements Servlet { @Override public void service(ServletRequest req, ServletResponse repo) { Map<String, Object> params = extractFromRequest(req); Map<String, Object> res = doBussiness(params); reponseTo(res); } ... }
看一个非线程安全的版本:
/** * 竞态条件(由于不恰当的执行时序而出现不正确的结果)导致非线程安全 */ @NotThreadSafe public class UnsafeCountingFactorizer implements Servlet { private long count = 0; @Override public void service(ServletRequest req, ServletResponse repo) { count++; //该操作并非原子(读取--自增--写入), 导致非线程安全 Map<String, Object> params = extractFromRequest(req); Map<String, Object> res = doBussiness(params); reponseTo(res); } }例如这种情况,预计值为11,结果为10:
看个实例:
/** * 延迟初始化的竞态条件 * 由于多个线程可能同时执行到instance == null, * 或者由于实例初始化过程比较耗费时间, * 这样有可能所谓的"单例"不再单例 */ @NotThreadSafe public class LazyInitRace { private ExpensiveObject instance; private LazyInitRace(){} public ExpensiveObject getInstance() { if (instance == null) { instance = new ExpensiveObject(); } return instance; } }
/** * 可通过java提供的原子变量(Atomic*) * 来解决竞态条件引起的非线程安全 */ @ThreadSafe public class CountingFactorizer implements Servlet { private AtomicLong count = new AtomicLong(0); @Override public void service(ServletRequest req, ServletResponse repo) { count.incrementAndGet(); //原子增加,该方法最后会调用Unsafe.compareAndSwapLong本地方法 Map<String, Object> params = extractFromRequest(req); Map<String, Object> res = doBussiness(params); reponseTo(res); } ... }
/** * 多个关联线程安全的状态对象导致线程安全 * 这里我们对lastNumber进行缓存,若请求的值与其相同,直接返回,反之计算 */ @NotThreadSafe public class UnsafeCachingFactorizer implements Servlet { private final AtomicReference<BigInteger> lastNumber = new AtomicReference<>(); private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<>(); @Override public void service(ServletRequest req, ServletResponse repo) { BigInteger i = extractFromRequest(req); //A线程发现不等,重新计算;(A未计算完) //B线程进入也发现不等,也重新计算(但其实有可能经过A计算后是相等的) //从而达不到缓存效果 if (i.equals(lastNumber.get())){ reponseTo(i, lastFactors); } else{ BigInteger[] factors = factor(i); lastNumber.set(i); lastFactors.set(factors); reponseTo(i, factors); } } ... }
/** * 通过synchronized实现线程安全,但性能低下 */ @ThreadSafe public class CachingFactorizer implements Servlet { private BigInteger lastNumber = new BigInteger(""); private BigInteger[] lastFactors = new BigInteger[]{}; @Override public synchronized void service(ServletRequest req, ServletResponse repo) { BigInteger i = extractFromRequest(req); if (i.equals(lastNumber)){ reponseTo(i,lastFactors); } else{ BigInteger[] factors = factor(i); lastNumber = i; lastFactors = factors; reponseTo(i, factors); } } }
/** * 通过分段synchronized提升性能 */ @ThreadSafe public class CachedFactorizer implements Servlet { private BigInteger lastNumber = new BigInteger(""); private BigInteger[] lastFactors = new BigInteger[] {}; private long hits; private long cacheHits; @Override public void service(ServletRequest req, ServletResponse repo) { BigInteger i = extractFromRequest(req); BigInteger[] factors = null; synchronized (this) { ++hits; if (i.equals(lastNumber)) { ++cacheHits; factors = lastFactors; } } if (factors == null) { factors = factor(i); synchronized (this) { lastNumber = i; lastFactors = factors; } } reponseTo(i, lastFactors); } ... }
不吝指正。