2012-03-27 70 views
3

这是我的代码..如何以及为什么此代码是线程安全的..?

@immutable // This is not a standard annotation .Only for Showing that behavior of Class 
class OneValueCached{ 
    private final BigInteger lastNumber; 
    private final BigInteger[] lastFactors; 
    public OneValueCached(BigInteger i,BigInteger[] factors){ 
     lastNumber=i; 
     lastFactors=Arrays.copyOf(factors, factors.length); 
    } 

    public BigInteger[] getFactors(BigInteger i){ 
     if(lastNumber==null || !lastNumber.equals(i)) 
      return null; 
     else 
      return Arrays.copyOf(lastFactors, lastFactors.length); 
    } 
} 

@threadSafe // This is not a standard annotation .Only for Showing that behavior of Class 
public class VolatileCachedFactorizer implements Servlet{ 
    private volatile OneValueCached cache=new OneValueCached(null, null); 

    public void service(ServletRequest req, ServletResponce resp){ 
     BigInteger i= extractFromRequest(req); 
     BigInteger[] factors=cache.getFactors(i); 
     if(factors==null){ // ---> line 1 
      factors=factor(i); // --> line 2 
      cache=new OneValueCached(i, factors); 
     } 

     encodeIntoResponse(resp,factors); 
    } 
} 

为什么类VolatileCachedFactorizer是线程根据但我的观点是...
1 @ 1号线如果2线程在同一时间到来在这一点上第一个thread检查条件,发现因子= null和第二个thread也检查同一条件后第1 thread暂停在线第2发现系数= NULL
,都将是创造新的OneValueCached对象的代码再怎么是线程安全的。根据预订是线程安全的..

感谢的

+0

“@ threadSafe”是什么注释?它可能是打字错误,也可能不是标准注释,因为标准命名约定是'@ ThreadSafe'。 (相同的@ @不可变) – Thomas 2012-03-27 06:57:22

+0

只是为了通知,我知道这不是一个标准注释... – 2012-03-27 06:58:37

+2

'return lastFactors = Arrays.copyOf(lastFactors,lastFactors.length);'看起来很奇怪。它大概是内部数组的防御副本,但是也会将内部状态重新分配给它发出的同一个副本。这不再是防御或不可改变的。其实,这是一个编译错误,因为'lastFactors'是最终的,不是? – Thilo 2012-03-27 07:11:01

回答

3

这是线程安全的,因为有从未在lastNumberlastFactors之间产生不一致,这可能会导致错误的因子分解。它不保证最小数量的保理会发生:OneValueCached可以创建多次,但这仍然是线程安全的。

+0

谢谢,我明白了。 :) – 2012-03-27 07:24:19

1

“线程安全性”的确切概念尚未在此处定义。你希望这个代码是线程安全的吗?

  1. 如果您期望涉及的所有对象的状态(就我所知,在此代码中)是一致的,那么它是线程安全的(如@artbristol解释)。
  2. 如果您期望同时调用service时创建一个Cache对象,则它不是线程安全的。

再一次,没有为这种情况定义线程安全行为,我们无法真正说清楚。

0

此代码是线程安全的。但我不认为Array.copyOf()在构造函数中是必要的。

0

虽然这是一年多以前提出的问题,但我仍然想给出我的解释。 实际上,这段代码是从第40页的“Java Concurrency in Practice”中采用的。作者声称VolatileCachedFactorizer是一个线程安全的servlet,因为servlet程序本身是由用户同时调用的。所以作者意味着如果可变 - -OneValueCached缓存可以一致地被线程读写,这意味着不会导致诸如lastNumber和lastFactors不匹配的情况,那么它将是线程安全的。我很困惑的是,本书声称只有在Arrays.copyOf()函数被使用,它将是线程安全的。但为什么?为什么需要Arrays.copyOf()?

0

Qisen,回答你的问题,需要Arrays.copyOf(),否则OneValueCache将不会是不可变的。如果在构建OneValueCache时没有复制这些因素,那么您应该让数组的引用(直到该点位于运行线程本地)转义。

相关问题