本文系转载,为方便整理和查看复制,源文地址为 https://www.cnblogs.com/panbingqi/p/11059196.html

如果是全局变量,i++是不安全的,因为java在操作i++的时候,是分步骤做的,可以理解为:
tp = i;
tp2 = i+1;
i=tp2;
如果线程1在执行第一条代码的时候,线程2访问i变量,这个时候,i的值还没有变化,还是原来的值,所以是不安全的。

从更底层的角度讲,主要是因为i++这个操作不是原子性的,这个会编译成i= i +1; 所以会出现多线程访问冲突问题。volatile虽然可以保证多线程对修改可见,但代码中用到了
i++, 主要是i++不是原子性操作,这个会编译成i = i +1,其实是做了3个步骤,一个是读取,修改,写入 。所以会出现多线程访问冲突问题

解决方案:

在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而java.util.concurrent.AtomicInteger是一个提供原子操作的Integer类,其提供了线程安全且高效的原子操作,是线程安全的。

AtomicInteger类的底层实现原理是利用处理器的CAS操作(Compare And Swap,比较与交换,一种有名的无锁算法)来检测栈中的值是否被其他线程改变,如果被改变则CAS操作失败。这种实现方法在CPU指令级别实现了原子操作,因此,其比使用synchronized来实现同步效率更高。

CAS操作过程都包含三个运算符:内存地址V、期望值E、新值N。当操作的时候,如果地址V上存放的值等于期望值E,则将地址V上的值赋为新值N,否则,不做任何操作,但是要返回原值是多少。这就保证比较和设置这两个动作是原子操作。系统主要利用JNI(Java Native Interface,Java本地接口)来保证这个原子操作,它利用CPU硬件支持来完成,使用硬件提供swap和test_and_set指令,但CPU下同一指令的多个指令周期不可中断,SMP(Symmetric Multi-Processing)中通过锁总线支持这两个指令的原子性

[转载]i++是否是线程安全的?相关推荐

  1. 【转载】进程与线程的区别

    进程是什么? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本:进程是程序的一次 ...

  2. 【转载】我是一个线程(修订版)

    原文:我是一个线程(修订版) 第一回 初生牛犊 我是一个线程,我一出生就被编了个号:0x3704,然后被领到一个昏暗的屋子里,在这里我发现了很多和我一模一样的同伴. 我身边的同伴0x6900 待的时间 ...

  3. java面试线程必备知识点,怼死面试官,从我做起

    转载自 java面试线程必备知识点,怼死面试官,从我做起 |--多线程一定好么? cpu密集不好 io密集好 |--如何减少上下文切换: 无锁并发(数据id根据Hash分段).CAS.最少线程 |-- ...

  4. Java中线程池,你真的会用吗

    转载自   Java中线程池,你真的会用吗 在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Ex ...

  5. 什么是线程安全,你真的了解吗

    转载自  什么是线程安全,你真的了解吗 记得今年3月份刚来杭州面试的时候,有一家公司的技术总监问了我这样一个问题,说你给我说说有哪些线程安全的类,我心里一想,呵呵,这我早都背好了,稀里哗啦说了一大堆, ...

  6. 非阻塞线程安全列表——ConcurrentLinkedDeque应用举例

    转载自  非阻塞线程安全列表--ConcurrentLinkedDeque应用举例 在java中,最常用的数据结构可能是列表.有数目不详的元素列表,你可以添加.阅读.或删除任何位置的元素.此外,并发列 ...

  7. jstack(查看线程)、jmap(查看内存)和jstat(性能分析)命令

    转载自  jstack(查看线程).jmap(查看内存)和jstat(性能分析)命令 1.Jstack  1.1   jstack能得到运行java程序的java stack和native stack ...

  8. 谈谈HashMap线程不安全的体现

    转载自 谈谈HashMap线程不安全的体现 HashMap的原理以及如何实现,之前在JDK7与JDK8中HashMap的实现中已经说明了. 那么,为什么说HashMap是线程不安全的呢?它在多线程环境 ...

  9. C++ :线程的暂停、恢复和停止

    转载:C++11: 线程的暂停和继续和停止_hai7song的专栏-CSDN博客_c++ 线程暂停 重点: 通过设置一个类,类里面加入线程,然后采用标志位来控线程的暂停.恢复和停止. 有点意思! #i ...

  10. c#语言窗体运行暂停指令,C#线程启动、暂停、恢复、停止怎么实现

    论坛的高手你们好,本人是一个菜鸟,肯请大家帮个忙实现如下功能: 首先窗体界面如下: 怎么实现"start"启动线程."pause"暂停线程."resu ...

最新文章

  1. 在windows上使用virt-manager
  2. 【机器学习】ROC曲线和PR(Precision-Recall)曲线的联系
  3. NameNode与DataNode的工作原理剖析
  4. sql 标量子查询_SQL Server 2017:标量子查询简化
  5. 模拟扑克牌随机选择(Java)
  6. pd虚拟机 17+win10、11懒人镜像 Mac
  7. ICMP Flood防范
  8. SSM整合篇--JSP介绍
  9. Quartz之CronExpression
  10. android 修改wifi设备名
  11. vue项目引入icon图标
  12. 如何自学黑客?自学黑客技术需要学多久?
  13. 感恩美文:生命中总有一些人值得感恩
  14. spring boot spring data 整合 redis redis keys * 出现 \xac\xed\x00\x05t\x00) 编码异常
  15. 生物工程学蛋白功能预测_海水中生长的工程细菌产生丝蛋白
  16. 电子数据取证之网站分析和重构基础
  17. 指定起终点的最短路算法-Dijkstra标号法及其改进
  18. 2021-05-18 英语单词总结
  19. 90分钟详解网络编程相关的细节处理丨 reactor丨网络io丨epoll丨C/C++丨Linux服务器开发丨后端开发丨Linux后台开发
  20. java pdf预览打印_Android实现PDF预览打印功能

热门文章

  1. MTK平台调试mipi屏问题小结
  2. SQL Server 2012 T-SQL 新特性
  3. python3 Tkinter GUI 试水
  4. MTV模型—urls和view
  5. vue2.0 之事件处理器
  6. Ns3 构建哑铃型拓扑,并实现两个点的TCP连接(详细请戳全文)
  7. 有锚点的链接页面刷新的问题
  8. oracle出现关键字该如何处理
  9. datatable 操作列根据权限动态展现_不会Excel透视表?教你一招轻松做出动态报表...
  10. express服务器多次访问数据库实例