线程安全问题是一个老生常谈的问题,那么多线程环境下究竟有那些问题呢?这么说吧,问题的形式多种多样的,归根结底的说是共享资源问题,无非可见性与有序性问题。

1. 可见性

可见性是对于内存中的共享资源来说。线程作为单一的控制流,在运行的程序内线程必须拥有一些资源作为开销。例如线程的堆栈和私有的程序计数器,线程之间的堆栈是不共享的,每个线程都有自己的堆栈,当然在Java中对于线程私有的内存区域只有程序执行栈与程序计数器。每个线程的运算操作都在自己的执行栈中进行。正是由于这样的结构设计,所以对于内存我们可以分为共享内存(Java中的堆)和工作内存(线程执行栈)。

对于共享内存而言,线程并不会直接去操作它,线程对于数据的运算也并不是直接发生在共享内存中的。这里有一个值拷贝的过程,线程在执行时会将用到的共享数据从共享内存中拷贝到工作内存中,从工作内存中完成计算之后,再复制到共享内存中。

所以当多线程操作共享内存时,一个线程修改了主内存的内容,那么其他线程是否能察觉到主内存的变化呢?对于可见性有一个经典的ABA问题。其实造成ABA问题的根本原因是因为内存的可见性问题。当一个线程修改了内存值之后,其他线程并不能立刻感知到。

2. 有序性

谈到有序性就要说起操作系统的调度算法了。我们知道线程是操作系统所能调度的最小单元,既然线程归操作系统调度,那么它是如何调度的呢?不同应用场景下的调度算法不太一致,常见的调度算法有时间片轮转算法与多级反馈队列,一般的分时操作系统都会采用时间片轮转算法进行线程的调度。

所谓时间片轮转算法,就是给每个线程一定的执行时间片。当这个线程的时间片用完之后就会调度另一个线程执行。通过这个算法的特点我们便知道,如果使用这样的算法,那么程序执行的单位变成了时间片,而并不是一次程序执行。正是这样就不能保障在时间片使用完毕后,程序能够按照正常的执行逻辑停止运行交出使用权。也就是说程序停止的位置具有不确定性。这样一来顺序的控制流就变得无序了。而无序也无伤大雅,重点是对于共享资源的访问,不能无序,要有序访问共享资源。

同时,有序性的另一个层面是线程同步问题。线程的调度由操作系统负责,多个线程执行的顺序我们无法得知。这样线程执行顺序的的无序有时也会带来问题。

Java线程安全问题的更多相关文章

  1. (转)java线程安全问题之静态变量、实例变量、局部变量

    java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定义,如 ...

  2. java线程安全问题以及使用synchronized解决线程安全问题的几种方式

    一.线程安全问题 1.产生原因 我们使用java多线程的时候,最让我们头疼的莫过于多线程引起的线程安全问题,那么线程安全问题到底是如何产生的呢?究其本质,是因为多条线程操作同一数据的过程中,破坏了数据 ...

  3. java线程安全问题之静态变量、实例变量、局部变量

    java多线程编程中,存在很多线程安全问题,至于什么是线程安全呢,给出一个通俗易懂的概念还是蛮难的,如同<java并发编程实践>中所说: 写道 给线程安全下定义比较困难.存在很多种定义,如 ...

  4. Java 线程安全问题

    线程安全问题产生原因: 1.多个线程操作共享的数据: 2.操作共享数据的线程代码有多条.   当一个线程正在执行操作共享数据的多条代码过程中,其它线程也参与了运算, 就会导致线程安全问题的发生. cl ...

  5. java线程安全问题原因及解决办法

    1.为什么会出现线程安全问题 计算机系统资源分配的单位为进程,同一个进程中允许多个线程并发执行,并且多个线程会共享进程范围内的资源:例如内存地址.当多个线程并发访问同一个内存地址并且内存地址保存的值是 ...

  6. Java 线程安全问题的本质

    原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94 目录: 线程安全问题的本质 理解CPU JVM虚拟机类比于操作系统 重排序 汇总 一些解释 ...

  7. java线程安全问题原理性分析

    1.什么是线程安全问题? 从某个线程开始访问到访问结束的整个过程,如果有一个访问对象被其他线程修改,那么对于当前线程而言就发生了线程安全问题:如果在整个访问过程中,无一对象被其他线程修改,就是线程安全 ...

  8. 关于 SimpleDateFormat 的非线程安全问题及其解决方案

    一直以来都是直接用SimpleDateFormat开发的,没想着考虑线程安全的问题,特记录下来(摘抄的): 1.问题: 先来看一段可能引起错误的代码: package test.date; impor ...

  9. Java多线程--线程安全问题的相关研究

    在刚刚学线程的时候我们经常会碰到这么一个问题:模拟火车站售票窗口售票.代码如下: package cn.blogs.com.isole; /* 模拟火车站售票窗口售票,假设有50张余票 */ publ ...

随机推荐

  1. kubernetes实战-配置中心(一)configmap资源

    在我们的环境中测试使用configmap资源,需要先对我们的环境进行一些准备,首先将dubbo服务调整为0个pod ,然后把zookeeper进行拆分: 拆分zk环境,模拟测试环境跟生产环境: 停止z ...

  2. Playbook 角色(Roles) 和 Include 语句

    简介 当我们刚开始学习运用 playbook 时,可能会把 playbook 写成一个很大的文件,到后来可能你会希望这些文件是可以方便去重用的,所以需要重新去组织这些文件. Include 语句 基本 ...

  3. 地址解析协议ARP与逆地址解析协议RARP

    IP地址是用来通信的,但是和硬件地址是有区别的.物理地址是数据链路层和物理层使用的地址,IP地址是网络层及以上各层使用的地址. 发送数据时,数据从高层向下层传输,使用IP地址的IP数据报交给下层的数据 ...

  4. USB2.0协议学习笔记---USB数据包结构

    USB包类型和传输过程  USB是一种串行总线,因此数据都是一位一位传输的,如同串口那样,但是USB在真实物理电路上却不是TTL电平,而是一种差分信号采用NRZI编码,就是用变化表示0,不变表示1,同 ...

  5. Install wx

    Ubuntu 16.04: 由于是PY交易, 实际上是安装wxPython: pip install -U \ -f https://extras.wxpython.org/wxPython4/ext ...

  6. Swift All in One

    Swift All in One Swift 5.3 https://github.com/apple/swift-evolution Xcode https://developer.apple.co ...

  7. git whoami

    git whoami $ git config --list $ git config --global --list # quit $ q $ git config user.name xgqfrm ...

  8. Azure 信用卡扣款 1 美元 & Azure 中国客服

    Azure 信用卡扣款 1 美元 & azure 中国客服 Azure 免费帐户常见问题 https://azure.microsoft.com/zh-cn/free/free-account ...

  9. 前端 & 技术团队 TL & 如何面试 & 如何带人

    前端 & 技术团队 TL & 如何面试 & 如何带人 面试 带人 作为 TL,深度了解你的团队非常重要,要去了解每个人的想法是什么,他的诉求是什么,他目前的状态怎么样,以及对他 ...

  10. css ::selection 选择文本改变样式

    .p1::selection{ background: red; color: #fff; }