【问题标题】:How and why This code is Thread Safe..?此代码如何以及为什么是线程安全的..?
【发布时间】:2012-03-27 06:51:44
【问题描述】:

这是我的代码..

@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 根据 Book 是线程但我的意思是..
1。 @ 第 1 行 如果 2 个线程同时出现在第 1 个 thread 检查条件并发现 factor=null 和第 2 个 thread 在第 1 个之后同时检查相同的条件thread 在第 2nd 行挂起,发现 factor=null
两者都将创建新的OneValueCached 对象然后这段代码是线程安全的.. 根据书这是线程安全的..

谢谢

【问题讨论】:

  • @threadSafe 是什么注解?它要么是拼写错误,要么不是标准注释,因为标准命名约定是@ThreadSafe。 (@immutable 也一样)
  • 请注意,我知道这不是标准注释...
  • return lastFactors=Arrays.copyOf(lastFactors, lastFactors.length); 看起来很奇怪。它可能会制作内部数组的防御性副本,但随后也会将内部状态重新分配给它分发的同一个副本。这不再是防御性的或一成不变的。实际上,这是一个编译错误,因为lastFactors 是最终的,不是吗?
  • 你能包含编译的代码吗?你在哪里定义了cached
  • cached 可能是cache。但是factor 方法呢?

标签: java multithreading thread-safety


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          Qisen,回答您的问题,需要 Arrays.copyOf() 否则 OneValueCache 不会是不可变的。如果您在构造 OneValueCache 时没有复制因子,那么您将让对数组的引用(在此之前它是正在运行的线程的本地)逃逸。

          【讨论】:

            猜你喜欢
            • 2014-03-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-04-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多