原 java 验证volatile不具有原子性
版权声明:本文为博主原创文章,请尊重他人的劳动成果,转载请附上原文出处链接和本声明。
本文链接:https://www.91mszl.com/zhangwuji/article/details/1125
(1)可见性。
(2)不保证原子性。
(3)禁止指令重排。
代码如下:
package com.mszl.thread;
/**
* 功能:验证volatile 不保证原子性
* 备注:更多资料请访问 http://www.91mszl.com
* @author bobo teacher
*/
class Acc{
volatile int number=0;
public void addPlus(){
number++;
}
}
public class Volatile1 {
public static void main(String[] args) {
Acc c=new Acc();
for(int i=1; i<=20; i++){ // 创建20个线程
Thread t=new Thread(new Runnable() {
@Override
public void run() {
for(int k=1; k<=1000; k++){ // 每个线程加1000次。一共20个线程。number=20 * 1000
c.addPlus();
}
}
});
t.start();
}
while(Thread.activeCount()>2){ // 因为有gc线程和main线程,所以这里是大于2
Thread.yield(); // 让其他线程先执行
}
System.out.println(Thread.currentThread().getName() + " >>> " + c.number);
}
}
执行结果:
main >>> 19735
注意:这里的执行结果也有可能是20000的,如果遇到了,请多执行几次。
代码如下:
package com.mszl.thread;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 功能:验证volatile 不保证原子性
* 备注:更多资料请访问 http://www.91mszl.com
* @author bobo teacher
*/
class Acc{
volatile int number=0;
public void addPlus(){
number++;
}
// volatile不保证原子性的解决方案
AtomicInteger ai=new AtomicInteger();
public void addMyAto(){
ai.getAndIncrement(); // 等价于number++
}
}
public class Volatile2 {
public static void main(String[] args) {
Acc c=new Acc();
for(int i=1; i<=20; i++){ // 创建20个线程
Thread t=new Thread(new Runnable() {
@Override
public void run() {
for(int k=1; k<=1000; k++){ // 每个线程加1000次。一共20个线程。number=20 * 1000
c.addPlus();
c.addMyAto();
}
}
});
t.start();
}
while(Thread.activeCount()>2){ // 因为有gc线程和main线程,所以这里是大于2
Thread.yield(); // 让其他线程先执行
}
System.out.println(Thread.currentThread().getName() + " >>> " + c.number);
System.out.println(Thread.currentThread().getName() + " AtomicInteger >>> " + c.ai);
}
}
执行结果:
main >>> 19866
main AtomicInteger >>> 20000
我们涉及到多线程++的时候采用AtomicInteger 来保证原子性。
2019-11-24 12:36:34 阅读(913)
名师出品,必属精品 https://www.91mszl.com
博主信息