java - 如果方法同步,是否需要 volatile?

标签 java multithreading volatile

我有多个线程访问 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);
  }

{

最佳答案

1。能见度

这个方法不会失败。如果您在每次访问字段时都进行同步,则每次线程持有相同的锁时都会保证对其所做的更改是可见的,如下所示:

enter image description here

来自 Java 并发实践 [ pdf ], 图3.1

所以没有必要让字段变易变。使用 AtomicInteger 可能会好得多的 getAndIncrement()incrementAndGet()方法,它们具有相同的目的,但具有更好的并发吞吐量(它们使用 native 功能而不是锁定,它们正是为此任务而设计的)——但要确保 AtomicInteger 的内存可见性本身是给定的(最简单的方法是将其设为最终值 - 它不会使 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。原子性

我可能在这篇文章中用过一次或两次“原子”,这意味着没有两个线程可以同时执行相同的代码,或者换句话说,操作不能被“分割”成多个部分线程可以并发。

+--- 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它为您实现了这种原子性。

关于java - 如果方法同步,是否需要 volatile?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34478956/

相关文章:

java - java多线程在不同操作系统上有不同吗?

java - 由 : java. sql.SQLException : Connection is not associated with a managed connection. org.jboss.resource.ada 引起

c - 当按值传递静态变量时会导致 c 中的竞争条件

c - 在 C 中使用线程时的奇怪行为

linux - 更多线程意味着更多上下文切换? Linux 内核也是如此吗?

c - ARM 过程调用标准是否允许与 C 标准相矛盾的 volatile 优化?

vb.net - 如何在 VB.net 中指定 volatile 的等效项?

java - JPA DBUnit HsqlDb : Disable constraint checks?

java - 如何在 JTextfied 中只接受 0 到 8 之间的数值?

java - Java将线程缓存刷新到实际副本时