在The Java Language Specification, Java SE 9 Edition中有一个声明:
Java编程语言允许线程访问共享变量(§17.1)。通常,为了确保共享变量的一致性和可靠性更新,线程应确保通过获取锁定来独占使用此类变量,通常会对这些共享变量实施互斥。
Java编程语言提供了第二种机制volatile字段,比某些用途的锁定更方便。
我试图找出使用volatile的目的比锁定更方便?
答案 0 :(得分:2)
我正在试图弄清楚使用volatile的目的是什么?更方便而不是锁定?
在简单的情况下,这是一个更方便的 1 解决方案,其中volatile是唯一需要同步的状态,并且操作本质上是原子的。
例如:
public class Processor extends Thread {
private volatile stopped;
public void run() {
while (!stopped) {
// do stuff
}
}
public void stop() {
stopped = true;
}
}
public class Test {
public static void main(String[] args) {
Processor p = new Processor();
p.start();
Thread.sleep(1000);
p.stop();
}
}
如果对stopped
使用常规变量,则在阅读和编写时需要使用synchronized
(或其他形式或锁定)...这样代码更多,不太方便。< / p>
public class Processor extends Thread {
private stopped;
public void run() {
while (!isStopped()) {
// do stuff
}
}
public synchronized void stop() {
stopped = true;
}
private synchronized boolean isStopped() {
return stopped;
}
}
但是,这仅适用于在简单情况下锁定的替代方法。如果受保护状态需要的不仅仅是原子读取和原子写入,那么它将无法工作。例如:
public class Counter {
private volatile int counter;
public void increment() {
counter = counter + 1;
}
private int get() {
return counter;
}
}
由于increment()
的实现方式,上述内容不是线程安全的。为了正确(线程安全)行为,increment = increment + 1
需要以原子方式完成。 volatile
不提供该保证。内存read
和write
操作都是原子的,但它们不是原子序列。
AFAIK,使用 Counter
变量实现volatile
没有线程安全的方法。您需要锁定或AtomicInteger
(通常依赖于CAS硬件支持......)
1 - 如果只计算代码行,会更方便。如果你也考虑到代码作者和维护者在推理上花费的工作,解决方案是正确的,我会认为“便利”在很大程度上是一种错觉。
在哪些情况下,易失性比锁定更好?
这是一个更难的问题,因为“更好”是一个加载的术语。但如果你的意思是“性能更高”,那么volatile
在工作的情况下通常会更好:
volatile
读取或写入只会导致内存障碍。Atomic
类型通常也使用CAS实现。这种分析有点粗糙,但最底层的是,如果volatile
能够胜任这项工作,那么它可能比替代方案更有效率。但有两点需要注意:
volatile
volatile
的性能优势太小而不显着。如果存在争用或同步瓶颈,则会发生更改。 答案 1 :(得分:1)
要完成Stephen C的答案,volatile关键字提供共享变量的原子读取和写入,然后在JVM内部不使用与synchronized块相反的任何监视器。
因此,对于共享的简单变量,从性能的角度来看,它应该更有效。
但正如已经提到的那样,它仅适用于简单的变量访问。
请参阅文档here
答案 2 :(得分:1)
为什么 volatile :它不涉及上下文切换或同步开销。写入总是将状态刷新到主存储器。
volatile 时:通常用于布尔变量,如果没有复合语句。即操作是原子的。 i++
不是原子的。
替代方案:使用CAS语句或锁定的原子变量。
答案 3 :(得分:1)
如果您有单个编写者线程和多个读者线程,则可以使用volatile
。
但如果你有多个作家和读者线程volatile
不提供数据一致性。
更多细节可以阅读@ Difference between volatile and synchronized in Java