【发布时间】:2021-09-05 09:05:20
【问题描述】:
我正在对处理多线程 Java 应用程序中的竞争条件的不同方法进行实验。像原子变量这样的策略,同步效果很好,但我没有看到使用 volatile 变量时问题得到解决。这里的代码和输出供参考。
您能否指导一下 volatile 变量仍会导致竞态条件的原因是什么?
package com.shyam.concurrency;
public class main {
public static void main(String[] args) {
demoClass dm1 = new demoClass();
Thread th1 = new Thread(()->{
int i =0;
do {
i++;
dm1.setCounter();
dm1.setAtomicCounter();
dm1.setSyncCounter();
dm1.setVolatileCounter();
} while (i < 100000);
});
Thread th2 = new Thread(()->{
int i =0;
do {
i++;
dm1.setCounter();
dm1.setAtomicCounter();
dm1.setSyncCounter();
dm1.setVolatileCounter();
} while (i < 100000);
});
th1.start();
th2.start();
try {
th1.join();
th2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Normal counter(Race condition) : " + dm1.getCounter() );
System.out.println("Synchronized counter is :" + dm1.getSyncCounter());
System.out.println("Atomic counter is :" + dm1.getAtomicCounter());
System.out.println("Volatile counter is :" + dm1.getVolatileCounter());
有增量逻辑的代码在这里:
package com.shyam.concurrency;
import java.util.concurrent.atomic.AtomicInteger;
public class demoClass {
private int counter ;
private int syncCounter;
private volatile int volatileCounter = 0;
private AtomicInteger atomicCounter = new AtomicInteger() ;
public int getAtomicCounter() {
return atomicCounter.intValue();
}
public void setAtomicCounter() {
this.atomicCounter.addAndGet(1);
}
public int getCounter() {
return counter;
}
public void setCounter() {
this.counter++;
}
public synchronized int getSyncCounter() {
return syncCounter;
}
public synchronized void setSyncCounter() {
this.syncCounter++;
}
public int getVolatileCounter() {
return volatileCounter;
}
public void setVolatileCounter() {
this.volatileCounter++;
}
}
这是我得到的输出:
Normal counter(Race condition) : 197971
Synchronized counter is :200000
Atomic counter is :200000
Volatile counter is :199601
【问题讨论】:
-
好吧,我还没有阅读你的代码,但问题可能是原子性。
volatile不提供,而您提到的其他两种方法提供。因此,只需为您的问题选择正确的方法即可。 -
现在我已经阅读了您的代码,问题肯定是原子性。
volatile众所周知不会帮助进行这种访问。它不起作用,因为规范说它不会。 -
对
volatile变量的读/修改/写操作不是原子操作。两个线程可以交错,一个正在读取,而另一个正在递增或其他方式。如果需要原子性,就不能选择只保证可见性的操作。
标签: java multithreading synchronized volatile atomicinteger