如果方法同步,是否需要 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 为您实现这种原子性。