验证volatile不保证原子性
程序员文章站
2024-03-22 09:19:16
...
验证volatile不保证原子性
* 原子性:完整性,不可分割性。某个线程在做某个业务时,不可以被加塞或被分割,需要整体完成,要么同时成功,要么同时失败。
* volatile不保证原子性原因:i++,实际上分为4步,取值,+,更新主物理内存;volatile不保证更新主物理内存时,线程竞争存在覆盖重写,丢数据。
* 解决方法:1 使用synchronized (大材小用) 2 使用juc下的 AtomicInteger(原子……)
代码:
class MyData{
//int number = 0 ;
volatile int number = 0 ;
public void setTo60(){
this.number = 60;
}
//此时number前加volatile修饰,但是不保证原子性
public void addPlusPlus(){
number ++;
}
AtomicInteger atomicInteger = new AtomicInteger();
public void addMyAtomic(){
atomicInteger.getAndIncrement();
}
}
/**
* 1 验证wolatile可见性
* 2 验证wolatile不保证原子性
* 原子性:完整性,不可分割性。某个线程在做某个业务时,不可以被加塞或被分割,需要整体完成,要么同时成功,要么同时失败。
* volatile不保证原子性原因:i++,实际上分为4步,取值,+,更新主物理内存;volatile不保证更新主物理内存时,线程竞争存在覆盖重写,丢数据。
* 解决方法:1 使用synchronized (大材小用) 2 使用juc下的 AtomicInteger(原子……)
* 3 验证wolatile禁止重排
*/
public class VolatileDemo {
public static void main(String[] args){
//seeOkByVolatile();
final MyData myData = new MyData();
for (int i =1;i<=20;i++) {
final Thread aa = new Thread() {
@Override
public void run() {
for (int j = 1; j<= 2000; j ++) {
myData.addPlusPlus();
myData.addMyAtomic();
}
};
};
aa.start();
};
//两个线程 主线程 和 垃圾回收线程
while (Thread.activeCount()>2){
Thread.yield();
}
//number 永远《=40000;atomicInteger=40000 因为更新主内存时覆盖值原因,丢失值。
System.out.println(Thread.currentThread().getName()+" final number is " + myData.number + "; final AtomicInteger is " + myData.atomicInteger);
}
}
下一篇: C语言宏的用法详解