这一章,我们要来验证volatile关键字不是原子性的,OK,还是用代码来说话。

①.线程类,操作i++ 500次

  1. package com.multiThread.thread;
  2. publicclassNumberThreadimplementsRunnable{
  3. privatevolatileint num =0;
  4. @Override
  5. publicvoid run(){
  6. for(int i =0;i<500;i++){
  7. num++;
  8. }
  9. }
  10. publicint getNum(){
  11. return num;
  12. }
  13. publicvoid setNum(int num){
  14. this.num = num;
  15. }
  16. }
②.测试类,创建5个线程同时执行
  1. package com.multiThread.test.automic;
  2. import com.multiThread.thread.NumberThread;
  3. publicclassAutomicTest{
  4. publicstaticvoid main(String[] args){
  5. NumberThread numThread =newNumberThread();
  6. for(int i =0;i<5;i++){
  7. Thread t =newThread(numThread);
  8. t.start();
  9. }
  10. try{
  11. Thread.sleep(1000);
  12. }catch(InterruptedException e){
  13. e.printStackTrace();
  14. }
  15. System.out.println(numThread.getNum());
  16. }
  17. }
多次运行结果:(正常结果2500居多)
  1. 2500
  2. 2282
  3. 2458
 
为什么造成这种现象?
首先我们要知道i++不是原子操作,是线程不安全的,它分为以下3步:
1.获取i的值
2.执行i+1的操作
3.将结果赋值给i
其次就算变量已经使用volatile关键字来修饰,只能保证读取全局变量num值的时候从主存拿到的是最新的值。
但是当多个线程同时操作自加的时候,如果之前取到的是同一个值,再自加后得到的值是相同的。
 
解决的方式如下两种:
1.可以使用synchronize关键字进行同步操作,这种情况需要把volatile去掉。因为synchronize本身就会操作工作内存和主内存直接的数据同步,此方式不再赘述。
2.将i++更改为线程安全的原子性操作,使用AtomicInteger替代i++
 
①.线程类
  1. package com.multiThread.thread;
  2. import java.util.concurrent.atomic.AtomicInteger;
  3. publicclassNumberThread2implementsRunnable{
  4. privateAtomicInteger num =newAtomicInteger();
  5. @Override
  6. publicvoid run(){
  7. for(int i =0;i<500;i++){
  8. num.incrementAndGet();
  9. }
  10. }
  11. publicAtomicInteger getNum(){
  12. return num;
  13. }
  14. publicvoid setNum(AtomicInteger num){
  15. this.num = num;
  16. }
  17. }
②.测试类
  1. package com.multiThread.test.automic;
  2. import com.multiThread.thread.NumberThread;
  3. import com.multiThread.thread.NumberThread2;
  4. publicclassAutomicTest{
  5. publicstaticvoid main(String[] args){
  6. NumberThread2 numThread2 =newNumberThread2();
  7. for(int i =0;i<5;i++){
  8. Thread t =newThread(numThread2);
  9. t.start();
  10. }
  11. try{
  12. Thread.sleep(1000);
  13. }catch(InterruptedException e){
  14. e.printStackTrace();
  15. }
  16. System.out.println(numThread2.getNum());
  17. }
  18. }
运行结果
  1. 2500
 
 
 
 
 
 
 

多线程(四)~数据操作的原子性,使用原子性操作AutomicInteger替换非原子性的i++的操作的更多相关文章

  1. Java多线程学习---------超详细总结(java 多线程 同步 数据传递 )

    目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么 ...

  2. volatile非原子性的示例

    volatile非原子性的示例 package com.stono.thread2.page124; public class MyThread extends Thread { volatile p ...

  3. volatile非原子性示例

    volatile非原子性示例 学习了:<Java多线程编程核心技术>高洪岩 著 Page124 package com.stono.thread2.page124_2; public cl ...

  4. JAVA笔记14__多线程共享数据(同步)/ 线程死锁 / 生产者与消费者应用案例 / 线程池

    /** * 多线程共享数据 * 线程同步:多个线程在同一个时间段只能有一个线程执行其指定代码,其他线程要等待此线程完成之后才可以继续执行. * 多线程共享数据的安全问题,使用同步解决. * 线程同步两 ...

  5. iOS开发——实战篇Swift篇&UItableView结合网络请求,多线程,数据解析,MVC实战

    UItableView结合网络请求,多线程,数据解析,MVC实战 学了这么久的swift都没有做过什么东西,今天就以自己的一个小小的联系,讲一下,怎么使用swift在实战中应用MVC,并且结合后面的高 ...

  6. java 多线程四

    java 多线程一 java 多线程二 java 多线程三 java 多线程四 一个生产者,消费者的例子: import java.util.Stack; /** * Created by root ...

  7. 原生js实现类的添加和删除,以及对数据的add和update、view ,ajax请求 ,页面离开的操作

    1 类操作 function hasClass(cla, element) { if(element.className.trim().length === 0) return false; var ...

  8. Unix环境高级编程(四)数据系统文件和信息

    本章主要介绍了Unix系统的正常运行要使用的与系统有关的数据文件和信息.如:口令文件,阴影文件.组文件.附加组.系统标识.时间和日期历程. 口令文件,即Unix系统用户数据库,存储在/etc/pass ...

  9. Java笔记16:多线程共享数据

    一.Thread实现 public class ThreadDemo4 { publicstaticvoid main(String[] args) { new ThreadTest4().start ...

随机推荐

  1. Kibana6.x.x源码分析--JavaScript中 "!~" 这样的符号是啥意思?

    看到源码中有一段JS代码不太懂,如下: 里面这个 "!~" 符号看到后有点儿方啊O__O "…,毛线意思? [查资料,解释如下]: indexOf returns -1 ...

  2. 洛谷 P2482 loj #2885 [SDOI2010]猪国杀 题解【模拟】【贪心】【搜索】

    好玩的模拟题. 以后要经常写模拟题鸭 题目描述 游戏背景 <猪国杀>是一种多猪牌类回合制游戏,一共有\(3\)种角色:主猪,忠猪,反猪.每局游戏主猪有且只有\(1\)只,忠猪和反猪可以有多 ...

  3. 解决页面使用overflow: scroll,overflow-y:hidden在iOS上滑动卡顿的问题

    解决页面使用overflow: scroll,overflow-y:hidden在iOS上滑动卡顿的问题 div{ width: 100%; overflow-y: hidden; -webkit-o ...

  4. JS 克隆Object.prototype.Clone

    我们知道,在js中,当object作为参数传递到函数中进行处理后,实际上是修改了传入的对象本身(或者说是对象的引用),但很多时候我们并不希望函数去修改我们的这些对象参数,这就需要使用到对象的克隆,我们 ...

  5. css3 渐变色

    Firefox可以使用角度来设定渐变的方向,而webkit只能使用x和y轴的坐标. 渐变可以创建类似于彩虹的效果,低版本的浏览器使用图片来实现,CSS3将会轻松实现网页渐变效果 粘贴代码 <di ...

  6. Mac上Node环境配置

    公司配备Mac笔记本,以前没用过mac开发项目,一开始依然是从node官网下载安装包,后来领导说最好是用brew安装软件,这样比较方便,安装和卸载,只要在命令行输入相应的 install 和 unin ...

  7. quartz使用(整合spring)

    quartz与spring整合后,还是需要Scheduler实例.JobDetail实例.Trigger实例,只不过是用FactoryBean的方式创建了. 在spring-context-suppo ...

  8. jsoup: Java HTML Parser

    jsoup  Java HTML Parser jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于j ...

  9. pycharm + git实现两台电脑代码同步

    说明:此篇文章是作者方便日后查阅所有,请不要按本文的方法搭建 1.下载msysygit,https://git-for-windows.github.io/ 点击download获取下载链接,可能由于 ...

  10. zookeeper 常用命令

    服务管理 启动ZK服务: zkServer.sh start 查看ZK状态: zkServer.sh status 停止ZK服务: zkServer.sh stop 重启ZK服务: zkServer. ...