如果方法同步,是否需要 volatile?
Volatile needed if method is synchronized?
我有多个线程访问 class Aufzahlen
并递增 cc 变量。我想知道我是否不把 cc 放在 volatile 上,但是我的方法放在 synchronized 上有没有错误的余地?由于 cc 变量一次只会被访问一次。
线程是否仍然可以在自己的缓存中拥有 cc 变量并因此弄乱它?我 运行 这个代码示例已经有一段时间了,到目前为止没有发现任何错误。
public class Aufzahlen {
private int cc=1;
public synchronized void aufzahlen() throws InterruptedException {
cc = cc +1;
}
public synchronized void printa() {
// TODO Auto-generated method stub
System.out.println("Thread: " + Thread.currentThread() + "Zahl: " + cc);
}
{
volatile
变量告诉编译器永远不要在读写操作中将它们的值缓存在寄存器中。 CPU 缓存(L1、L2 等)仍在使用。
如果对该变量的所有访问(在 class 的单个实例中)都来自多个线程,则它们都应该受到保护。
如果您有兴趣在没有同步的情况下从另一个线程读取此 cc
值,那么是的,将其设为 volatile
。这将有效地使同步成为写锁。
由于同步块,您的源代码没有问题。字段cc
将只能同时访问一个线程,因为不允许两个不同的线程同时执行一个同步块。
1。能见度
这个方法不会失败。如果每次访问一个字段时都进行同步,则每次线程持有相同的锁时,保证对它的更改是可见的,如下所示:
来自Java Concurrency In Practice [pdf],图3.1
所以没有必要让字段变易变。使用 AtomicInteger
's getAndIncrement()
and incrementAndGet()
methods, which serve the same purpose, but with better concurrency throughput (they use native functionality instead of locking, they have been designed for exactly this task) - but make sure that memory visbility of the AtomicInteger
itself is given (the easiest way to do this is make it final - it won't make the AtomicInteger
的最终值可能会更好。
public class Aufzahlen {
private final AtomicInteger atomicInt = new AtomicInteger(1); // set initial value with constructor argument
public void aufzahlen() {
atomicInt.incrementAndGet();
} // no need for synchronization because updates are atomic and are automatically visible
}
2。原子性
我可能在这个post中用过一次或两次"atomic",这意味着没有两个线程可以并发执行相同的代码,或者换句话说,该操作不能"divided" 分成多个部分,多个线程可以同时在其中。
+--- Function aufzählen() without synchronization and with i++ ---------------+
| |
| [Get i from field] --> [Increment i locally] --> [Write new value to field] |
| ^ ^ |
| | | |
| "Race condition", multiple threads could be at these stages |
| -> operation not atomic |
+-----------------------------------------------------------------------------+
我刚刚演示了什么不是原子操作,你可以使用synchronized
使这个操作成为原子操作(下一个线程需要等待第一个完成整个方法)或者你可以使用AtomicInteger
为您实现这种原子性。
我有多个线程访问 class Aufzahlen
并递增 cc 变量。我想知道我是否不把 cc 放在 volatile 上,但是我的方法放在 synchronized 上有没有错误的余地?由于 cc 变量一次只会被访问一次。
线程是否仍然可以在自己的缓存中拥有 cc 变量并因此弄乱它?我 运行 这个代码示例已经有一段时间了,到目前为止没有发现任何错误。
public class Aufzahlen {
private int cc=1;
public synchronized void aufzahlen() throws InterruptedException {
cc = cc +1;
}
public synchronized void printa() {
// TODO Auto-generated method stub
System.out.println("Thread: " + Thread.currentThread() + "Zahl: " + cc);
}
{
volatile
变量告诉编译器永远不要在读写操作中将它们的值缓存在寄存器中。 CPU 缓存(L1、L2 等)仍在使用。
如果对该变量的所有访问(在 class 的单个实例中)都来自多个线程,则它们都应该受到保护。
如果您有兴趣在没有同步的情况下从另一个线程读取此 cc
值,那么是的,将其设为 volatile
。这将有效地使同步成为写锁。
由于同步块,您的源代码没有问题。字段cc
将只能同时访问一个线程,因为不允许两个不同的线程同时执行一个同步块。
1。能见度
这个方法不会失败。如果每次访问一个字段时都进行同步,则每次线程持有相同的锁时,保证对它的更改是可见的,如下所示:
来自Java Concurrency In Practice [pdf],图3.1
所以没有必要让字段变易变。使用 AtomicInteger
's getAndIncrement()
and incrementAndGet()
methods, which serve the same purpose, but with better concurrency throughput (they use native functionality instead of locking, they have been designed for exactly this task) - but make sure that memory visbility of the AtomicInteger
itself is given (the easiest way to do this is make it final - it won't make the AtomicInteger
的最终值可能会更好。
public class Aufzahlen {
private final AtomicInteger atomicInt = new AtomicInteger(1); // set initial value with constructor argument
public void aufzahlen() {
atomicInt.incrementAndGet();
} // no need for synchronization because updates are atomic and are automatically visible
}
2。原子性
我可能在这个post中用过一次或两次"atomic",这意味着没有两个线程可以并发执行相同的代码,或者换句话说,该操作不能"divided" 分成多个部分,多个线程可以同时在其中。
+--- Function aufzählen() without synchronization and with i++ ---------------+
| |
| [Get i from field] --> [Increment i locally] --> [Write new value to field] |
| ^ ^ |
| | | |
| "Race condition", multiple threads could be at these stages |
| -> operation not atomic |
+-----------------------------------------------------------------------------+
我刚刚演示了什么不是原子操作,你可以使用synchronized
使这个操作成为原子操作(下一个线程需要等待第一个完成整个方法)或者你可以使用AtomicInteger
为您实现这种原子性。