对于Java中的运算操作,例如自增或自减,若没有进行额外的同步操作,在多线程环境下就是线程不安全的。num++解析为num=num+1,明显,这个操作不具备原子性,多线程并发共享这个变量时必然会出现问题。测试代码如下:
class AtomicIntegerTest {
private static final int THREADS_COUNT = 20;
// 加volatile不管用
// public static volatile int count = 0;
// 原子操作
public static AtomicInteger count = new AtomicInteger(0);
public static void increase() {
// count++;
count.incrementAndGet();
}
public static void main(String[] args) {
Thread[] threads = new Thread[THREADS_COUNT];
for (int i = 0; i < THREADS_COUNT ;i++) {
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
increase();
}
}
});
threads[i].start();
}
int i = Thread.currentThread().getThreadGroup().activeCount();
int activeCount = Thread.activeCount();
System.out.println("i:"+i+",activeCount:"+activeCount);
while (Thread.activeCount() > 2) {
Thread.yield();
}
int jieshu = Thread.currentThread().getThreadGroup().activeCount();
System.out.println("jieshu:"+jieshu+",activeCount:"+Thread.activeCount());
System.out.println(count);
}
}
这里运行了20个线程,每个线程对count变量进行1000此自增操作,如果上面这段代码能够正常并发的话,最后的结果应该是20000才对,
不用AtomicInteger,用volatile修饰的count,运行结果总是一个小于20000的数字;
去掉volatile也是这样,换成AtomicInteger每次运行结果就是20000;
volatile的特性:
1、保证变量在线程间可见,对volatile变量所有的写操作都能立即反应到其他线程中,换句话说,volatile变量在各个线程中是一致的(得益于java内存模型—"先行发生原则");
2、禁止指令的重排序优化;
结论:基于volatile变量的运算在并发下是安全的,因为核心点在于java里的运算(比如自增)并不是原子性的。
问题:什么是原子性操作
有几个新的概念,非阻塞同步????CAS指令(Compare-And-Swap比较并交换),Unsafe类的CAS操作????
同步:多线程并发访问共享数据时,保证共享数据再同一时刻只被一个或一些线程使用。
相关文章:https://blog.csdn.net/fanrenxiang/article/details/80623884
网友评论