Java 此代码如何以及为什么是线程安全的。。?

Java 此代码如何以及为什么是线程安全的。。?,java,multithreading,thread-safety,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,BigInte

这是我的密码

@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);
    }
}
为什么classVolatileCachedFactorizer是根据这本书编写的,但我的观点是..
1@第1行如果两个线程同时出现在该点上,则第1行线程检查条件并找到因子=null和第2行线程也会在第1行线程挂起第2行
并找到因子=null
这两个对象都将创建新的
OneValueCached
对象,然后说明此代码如何是线程安全的。。根据这本书,这是线程安全的


Thank's

它是线程安全的,因为
lastNumber
lastFactors
之间从来没有不一致的地方,这可能导致不正确的因子分解。它不能保证将进行最小数量的分解:可以多次创建
OneValueCached
,但这仍然是线程安全的。

这里没有定义“线程安全”的确切概念。要使此代码是线程安全的,您希望发生什么/不会发生什么

  • 如果您希望所涉及的所有对象的状态(据我在代码中所见)都是一致的,那么它是线程安全的(正如@artbristol所解释的)
  • 如果您希望在同时调用
    服务
    时创建一个
    缓存
    对象,那么它不是线程安全的

  • 同样,如果没有对这种情况下的线程安全行为的定义,我们无法真正确定。

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

    虽然这是一个一年多前提出的问题,但我还是想解释一下。
    事实上,这段代码取自第40页的“Java并发实践”。作者声称VolatileCachedFactorizer是一个线程安全的servlet,因为该servlet程序本身是由用户并发调用的。因此,作者的意思是,如果可变--OneValueCached缓存可以由线程一致地读写,这意味着不会导致lastNumber和lastFactors等情况不匹配,那么它将是线程安全的。我感到困惑的是,这本书声称只有使用Arrays.copyOf()函数,它才是线程安全的。但是为什么?为什么需要Arrays.copyOf()呢?

    Qisen,回答你的问题,Arrays.copyOf()是必需的,因为否则OneValueCache将不会是不变的。如果在构造OneValueCache时没有复制因子,则会让对数组的引用(直到该点位于运行线程的本地)转义。

    什么是注释
    @threadSafe
    ?它要么是打字错误,要么不是标准注释,因为标准命名约定是
    @ThreadSafe
    。(与
    @immutable
    相同)请注意,我知道这不是一个标准的注释…
    返回lastFactors=Arrays.copyOf(lastFactors,lastFactors.length)似乎很奇怪。它可能会生成内部数组的防御副本,但也会将内部状态重新分配给它分发的同一副本。这不再是防御性的或一成不变的。实际上,这是一个编译错误,因为
    lastFactors
    是最终的,否?您能包括编译的代码吗?您在哪里定义了
    cached
    cached
    可能是
    cache
    。但是
    因子
    方法呢?