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

时间:2012-03-27 06:51:45

标签: java multithreading thread-safety

这是我的代码..

@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);
    }
}

为什么class VolatileCachedFactorizer Book 的主题但是我的观点是...... 的 1。 @第1行如果2个帖子同时在该点thread检查条件,并且发现 factor = null 和第2 thread也检查相同的条件第一次thread暂停在第二行后的同一时间,发现 factor = null
并且两者都将创建新的OneValueCached对象然后这个代码是如何线程安全的..根据书,这是线程安全..

感谢的

5 个答案:

答案 0 :(得分:3)

它是线程安全的,因为lastNumberlastFactors之间永远不会出现不一致,这可能导致不正确的因子分解。它不能保证最小量的因子分配将发生:OneValueCached可以多次创建,但仍然是线程安全的。

答案 1 :(得分:1)

这里没有定义“线程安全”的确切概念。对于这个代码是线程安全的,你期望发生什么/不发生什么?

  1. 如果你期望所涉及的所有对象的状态(在我的代码中可以看到)保持一致,那么它是线程安全的(如@artbristol所解释的那样)。
  2. 如果在同时调用Cache时期望单个创建service对象,则它不是线程安全的。
  3. 同样,如果没有为这种情况定义线程安全行为,我们无法确切地说出来。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

Qisen,回答你的问题,需要使用Arrays.copyOf(),因为否则OneValueCache不会是不可变的。如果在构造OneValueCache时没有复制因子,那么您将允许对该数组的引用(直到该点为正在运行的线程的本地)进行转义。