Java并发编程Volatile不能保证数据同步.docx

上传人:自*** 文档编号:126227261 上传时间:2020-03-23 格式:DOCX 页数:7 大小:35.64KB
返回 下载 相关 举报
Java并发编程Volatile不能保证数据同步.docx_第1页
第1页 / 共7页
Java并发编程Volatile不能保证数据同步.docx_第2页
第2页 / 共7页
Java并发编程Volatile不能保证数据同步.docx_第3页
第3页 / 共7页
Java并发编程Volatile不能保证数据同步.docx_第4页
第4页 / 共7页
Java并发编程Volatile不能保证数据同步.docx_第5页
第5页 / 共7页
点击查看更多>>
资源描述

《Java并发编程Volatile不能保证数据同步.docx》由会员分享,可在线阅读,更多相关《Java并发编程Volatile不能保证数据同步.docx(7页珍藏版)》请在金锄头文库上搜索。

1、Java并发编程:Volatile不能保证数据同步在本篇博文中,将给出一个实例去验证volatile修饰的变量并不能保证其数据同步。在本篇博文中,将给出一个实例去验证volatile修饰的变量并不能保证其数据同步。Java内存模型规定了所有变量都存储在主内存中,每条线程都有自己的工作内存,线程的工作内存保存了被该线程使用到变量的主内存副本拷贝,线程 对变量的所有操作(读取,赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程也不能直接访问对方工作内存中的变量,线程间变量值的 传递均需要通过主内存来完成,线程,主内存,工作内存三者的交互关系如图所示。当一个变量定义成volati

2、le之后, 保证了此变量对所有线程的可见性,也就是说当一条线程修改了这个变量的值,新的值对于其它线程来说是可以立即得知的.此时,该变量的读写操作直接在主内存中完成.Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。Volatile variables share the visibility features of synchronized, but none of the atomicity features.虽然增量操作(x+)看上去类似一个单独操作,实际上它是一个由读取修改写入操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供

3、必须的原子特性。While the increment operation (x+) may look like a single operation, it is really a compound read-modify-write sequence of operations that must execute atomically - and volatile does not provide the necessary atomicity.在多线程并发的环境下, 各个线程的读/写操作可能有重叠现象, 在这个时候, volatile并不能保证数据同步.下面将给出一个实例:实例 = 50

4、0个线程一起运行,每个线程对1到100求和1000次操作,然后将一个volatile共享变量值加1. 当500个线程都完成操作之后, 期望的值是500,因为每个线程执行完毕之后都会对这个volatile变量加1.一直循环执行这个程序,直到出现volatile变量的值小于500为止,也就是出现数据不同步。1. publicclassNonSafeThreadimplementsRunnable2. 3. /*共享资源,每个线程执行完之后加1*/4. privatevolatileintvolatileCount=0;5. 6. publicvoidrun()7. 8. /*9. *每个线程调用s

5、um100()方法,1000次10. */11. 12. for(inti=1;i=1000;i+)13. sum100();14. 15. 16. /*17. *计算完毕之后,volatileCount加118. */19. 20. increase();21. 22. 23. privatevoidincrease()24. 25. volatileCount+;26. 27. 28. /*29. *对1到100求和30. */31. privateintsum100()32. intresult=0;33. for(inti=1;i=100;i+)34. result+=i;35. 36

6、. returnresult;37. 38. 39. /*40. *returnthevolatileCount41. */42. publicintgetVolatileCount()43. returnvolatileCount;44. 45. 46. 1. /*2. *authorEric3. *4. *version1.05. */6. 7. publicclassNonSafeThreadTest8. 9. publicstaticvoidmain(Stringargs)10. 11. /*记录循环次数*/12. intloopCount=0;13. 14. /*以main函数主线程

7、创建一个是线程组*/15. ThreadGroupthreadGroup=Thread.currentThread().getThreadGroup();16. 17. for(;)18. loopCount+;19. 20. /*21. *启动500个线程,初始化的线程会添加到当前线程组中22. */23. NonSafeThreadnonSafeThread=newNonSafeThread();24. startThreads(nonSafeThread);25. 26. /*27. *如果线程组中除了主线程之外,还有其它线程,则休眠5毫秒,然后再判断线程组中剩余的线程数,直到只剩下主线

8、程一个为止。28. */29. while(!isOnlyMainThreadLeft(threadGroup)30. sleep(5);31. 32. 33. /*34. *500个线程运行完毕,那么此时的volatile变量volatileCount的值应该500,因为每个线程将其值加1。35. *36. *验证是否出现线程不安全的情况。37. */38. validate(loopCount,nonSafeThread.getVolatileCount(),500);39. 40. 41. 42. /*43. *启动500个线程44. */45. privatestaticvoidsta

9、rtThreads(NonSafeThreadnonSafeThread)46. 47. for(inti=0;i500;i+)48. newThread(nonSafeThread).start();49. 50. 51. 52. /*53. *验证是否出现线程不安全的情况。如果是,则打印出线程不安全的信息。54. */55. privatestaticvoidvalidate(intloopCount,intactualValue,56. intexpectedValue)57. if(!isVolatileCountExpected(actualValue,expectedValue)5

10、8. printNonSafeMessage(loopCount,actualValue,expectedValue);59. /*60. *正常退出程序。61. */62. System.exit(0);63. 64. 65. 66. /*67. *在控制台打印出现线程不安全时的信息。68. */69. privatestaticvoidprintNonSafeMessage(intloopCount,intactualValue,70. intexpectedValue)71. System.out.println(String.format(72. 第%d次循环,出现线程不安全的情况,v

11、olatile的值不正确,期望值是%d,但是500个线程运行的情况下是%d,73. loopCount,expectedValue,actualValue);74. 75. 76. /*77. *判断实际中的volatile值与期望值是否一致。78. */79. privatestaticbooleanisVolatileCountExpected(intactualValue,80. intexpectedValue)81. returnactualValue=expectedValue;82. 83. 84. /*85. *让线程休眠millis毫秒86. */87. privatestaticvoidsleep(longmillis)88. try89. Thread.sleep(millis);90. catch(InterruptedExceptione)91. /TODOAuto-generatedcatchblock92. e.printStackTrace(

展开阅读全文
相关资源
相关搜索

当前位置:首页 > IT计算机/网络 > 其它相关文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号