这是在一次技术会谈中向我提出的一个问题。
public class MyClass {
volatile int i;
}
我使用上面的MyClass作为ThreadLocal,那么在这里使用任何volatile变量有什么用呢?
final ThreadLocal<MyClass> threadLocal = new ThreadLocal<MyClass>();
答案 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)
公共类ThreadLocal
此类提供线程局部变量。这些变量不同 来自他们的正常对应者,每个访问一个的线程 (通过其get或set方法)有自己的,独立初始化 变量的副本。
Java编程语言允许线程访问共享 变量(第17.1节)。通常,确保共享变量 一致且可靠地更新,线程应确保它具有 通过获得锁定来独占使用这些变量, 通常,对这些共享变量实施互斥。
Java编程语言提供了第二种机制,即volatile 字段,这比某些目的的锁定更方便。
因此,在您的示例中,每个线程都有自己的MyClass实例。如果它是MyClass的唯一使用,则允许对i
进行并发访问。
volatile是“强制互斥”的“比锁定更方便”机制的关键词。
因此,您不需要此代码中的volatile。
此外,它会降低性能。