无同步的并发计数结果不对
2016-10-14 00:00
141 查看
Demo类
下面的demo即使有volatile属性也是不能保证计数器的正确性的。
接下来使用AtomicInteger做计数器,就可以不用volatile变量了。
com.oldratlee.fucking.concurrency.WrongCounterDemo。
Demo说明
主线程中开启2个任务线程执行并发递增计数。主线程最终结果检查。问题说明
计数值不对。快速运行
mvn compile exec:java -Dexec.mainClass=com.oldratlee.fucking.concurrency.WrongCounterDemo
下面的demo即使有volatile属性也是不能保证计数器的正确性的。
public class WrongCounterDemo { private static final int INC_COUNT = 100000000; volatile int counter = 0; public static void main(String[] args) throws Exception { WrongCounterDemo demo = new WrongCounterDemo(); System.out.println("Start task thread!"); Thread thread1 = new Thread(demo.getConcurrencyCheckTask()); thread1.start(); Thread thread2 = new Thread(demo.getConcurrencyCheckTask()); thread2.start(); thread1.join(); thread2.join(); int actualCounter = demo.counter; int expectedCount = INC_COUNT * 2; if (actualCounter != expectedCount) { // 在我的开发机上,几乎必现!即使counter上加了volatile。(简单安全的解法:使用AtomicInteger) System.err.printf("Fuck! Got wrong count!! actual %s, expected: %s.", actualCounter, expectedCount); } else { System.out.println("Wow... Got right count!"); } } ConcurrencyCheckTask getConcurrencyCheckTask() { return new ConcurrencyCheckTask(); } private class ConcurrencyCheckTask implements Runnable { @Override public void run() { for (int i = 0; i < INC_COUNT; ++i) { ++counter; } } } }
接下来使用AtomicInteger做计数器,就可以不用volatile变量了。
public class WrongCounterDemo { private static final int INC_COUNT = 100000000; AtomicInteger counter = new AtomicInteger(0); public static void main(String[] args) throws Exception { WrongCounterDemo demo = new WrongCounterDemo(); System.out.println("Start task thread!"); Thread thread1 = new Thread(demo.getConcurrencyCheckTask()); thread1.start(); Thread thread2 = new Thread(demo.getConcurrencyCheckTask()); thread2.start(); thread1.join(); thread2.join(); int actualCounter = demo.counter.intValue(); int expectedCount = INC_COUNT * 2; if (actualCounter != expectedCount) { // 在我的开发机上,几乎必现!即使counter上加了volatile。(简单安全的解法:使用AtomicInteger) System.err.printf("Fuck! Got wrong count!! actual %s, expected: %s.", actualCounter, expectedCount); } else { System.out.println("Wow... Got right count!"); } } ConcurrencyCheckTask getConcurrencyCheckTask() { return new ConcurrencyCheckTask(); } private class ConcurrencyCheckTask implements Runnable { @Override public void run() { for (int i = 0; i < INC_COUNT; ++i) { counter.incrementAndGet(); } } } }
相关文章推荐
- iOS开发-队列和同步异步执行的结果分析
- 并发 并行 同步 异步 多线程 阻塞 非阻塞
- 等待Ajax结果 再提交表单(ajax同步)
- 并发是个什么鬼之同步工具类CountDownLatch
- Linux并发与同步专题 (1)原子操作和内存屏障
- 有关java并发程序同步概念的全部意义
- 云端呼叫中心坐席并发测试结果
- 大数据量下高并发同步
- Java并发与同步
- Java并发库(十九):同步集合类的使用BlockingQueue、
- iOS多线程并发,串行,同步,异步
- 两种高效的并发模式:半同步/半异步和领导者/追随者
- 并行、并发、同步和互斥
- 同步,异步,阻塞,非阻塞,并发,并行
- 构建高效且可伸缩的结果缓存引申的并发测试规范化
- 《面向模式的软件体系结构2-用于并发和网络化对象模式》读书笔记(11)--- 同步模式与定界加锁
- 关于Web开发里并发、同步、异步以及事件驱动编程的相关技术
- Java并发(具体实例)——构建高效且可伸缩的结果缓存
- Java学习笔记—多线程(同步容器和并发容器)
- Java并发编程4.5-同步策略的文档化