在ThreadLocal实例中获取volatile变量的目的

时间:2015-01-30 05:58:53

标签: java multithreading thread-local

这是在一次技术会谈中向我提出的一个问题。

public class MyClass {

    volatile int i;
}

我使用上面的MyClass作为ThreadLocal,那么在这里使用任何volatile变量有什么用呢?

final ThreadLocal<MyClass> threadLocal = new ThreadLocal<MyClass>();

3 个答案:

答案 0 :(得分:1)

如果该实例仅与ThreadLocal一起使用且未传递,则volatile中似乎没有多大意义。

但请注意,MyClass只是一个类似于任何其他的类:没有什么能阻止它在不涉及线程本地存储的上下文中使用。在这些情况下,变量可能有意义volatile

答案 1 :(得分:0)

Java中的Volatile保证volatile变量的值总是从主内存中读取,而不是从Thread的本地缓存中读取。

在某些情况下,易失性变量可以用作在Java中实现同步的替代方法,例如可见性。使用volatile变量保证所有读者线程一旦写入操作完成就会看到volatile变量的更新值,没有volatile关键字不同的读者线程可能会看到不同的值。让我们借助一个例子来理解这一点。

public class C {
   private volatile int COUNTER=0;

    public static void main(String... q)
    {
        new C().call();
    }

    public void call()
    {
        new A().start();
        new B().start();
    }

    class A extends Thread
    {
        public void run()
        {
            int i =0;
            while(i<100)
            {
                COUNTER++;
                System.out.println(" A COUNTER : "+COUNTER+" *** "+"i : "+i);
                try{
                    Thread.sleep(50);
                }
                catch(Exception e)
                {

                }
                i++;
            }
        }
    }

    class B extends Thread
    {
        public void run()
        {
            int i =0;
            while(i<100)
            {
                COUNTER++;
                 System.out.println(" B COUNTER : "+COUNTER+" *** "+"i : "+i);
                   try{
                    Thread.sleep(50);
                }
                catch(Exception e)
                {

                }
                i++;
            } 
        }
    }
}

我在两个线程之间共享了COUNTER变量,并使用了volatile而不是同步,以便更新的值将在主内存中全局共享,其他线程将获得更新值。

通过替换:

再次尝试上面的代码

private volatile int COUNTER = 0;

private int COUNTER = 0;

重新运行程序并记下差异。

答案 2 :(得分:0)

根据the documentation

  

公共类ThreadLocal

     

此类提供线程局部变量。这些变量不同   来自他们的正常对应者,每个访问一个的线程   (通过其get或set方法)有自己的,独立初始化   变量的副本。

根据the specification

  

Java编程语言允许线程访问共享   变量(第17.1节)。通常,确保共享变量   一致且可靠地更新,线程应确保它具有   通过获得锁定来独占使用这些变量,   通常,对这些共享变量实施互斥。

     

Java编程语言提供了第二种机制,即volatile   字段,这比某些目的的锁定更方便。

因此,在您的示例中,每个线程都有自己的MyClass实例。如果它是MyClass的唯一使用,则允许对i进行并发访问。

volatile是“强制互斥”的“比锁定更方便”机制的关键词。

因此,您不需要此代码中的volatile。

此外,它会降低性能。