作者:a60782885

blog.csdn.net/a60782885/article/details/77803757

注,本篇只是解析基本概念,用作面试应答,非深入

对于Java并发编程,一般来说有以下的关注点:

  1. 线程安全性,正确性。

  2. 线程的活跃性(死锁,活锁)

  3. 性能

其中线程的安全性问题是首要解决的问题,线程不安全,运行出来的结果和预期不一致,那就连基本要求都没达到了。

保证线程的安全性问题,本质上就是保证线程同步,实际上就是线程之间的通信问题。我们知道,在操作系统中线程通信有以下几种方式:

  1. 信号量

  2. 信号

  3. 管道

  4. 共享内存

  5. 消息队列

  6. socket

java中线程通信主要使用共享内存的方式。共享内存的通信方式首先要关注的就是可见性和有序性。而原子性操作一般都是必要的,所以主要关注这三个问题。

1.原子性

原子性是指操作是不可分的。其表现在于对于共享变量的某些操作,应该是不可分的,必须连续完成。例如a++,对于共享变量a的操作,实际上会执行三个步骤:

  1. 读取变量a的值

  2. a的值+1

  3. 将值赋予变量a 。

这三个操作中任何一个操作过程中,a的值被人篡改,那么都会出现我们不希望出现的结果。所以我们必须保证这是原子性的。Java中的锁的机制解决了原子性的问题。

2.可见性

可见性是值一个线程对共享变量的修改,对于另一个线程来说是否是可以看到的。

为什么会出现这种问题呢?

我们知道,java线程通信是通过共享内存的方式进行通信的,而我们又知道,为了加快执行的速度,线程一般是不会直接操作内存的,而是操作缓存。

java线程内存模型:

实际上,线程操作的是自己的工作内存,而不会直接操作主内存。如果线程对变量的操作没有刷写会主内存的话,仅仅改变了自己的工作内存的变量的副本,那么对于其他线程来说是不可见的。而如果另一个变量没有读取主内存中的新的值,而是使用旧的值的话,同样的也可以列为不可见。

对于jvm来说,主内存是所有线程共享的java堆,而工作内存中的共享变量的副本是从主内存拷贝过去的,是线程私有的局部变量,位于java栈中。

那么我们怎么知道什么时候工作内存的变量会刷写到主内存当中呢?

这就涉及到java的happens-before关系了。

在JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before关系。

这个人的博客写的不错:http://ifeve.com/easy-happens-before/。

简单来说,只要满足了happens-before关系,那么他们就是可见的。

例如:

线程A中执行i=1,线程B中执行j=i。如果线程A的操作和线程B的操作满足happens-before关系,那么j就一定等于1,否则j的值就是不确定的。

happens-before关系如下:

  1. 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作;

  2. 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作;

  3. volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作;

  4. 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;

  5. 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作;

  6. 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生;

  7. 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;

  8. 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始;

从上面的happens-before规则,显然,一般只需要使用volatile关键字,或者使用锁的机制,就能实现内存的可见性了。

3.有序性

有序性是指程序在执行的时候,程序的代码执行顺序和语句的顺序是一致的。

为什么会出现不一致的情况呢?

这是由于重排序的缘故。

在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。

举个例子:

线程A:

context = loadContext();
inited = true;

线程B:

while(!inited ){sleep
}
doSomethingwithconfig(context);

如果线程A发生了重排序:

inited = true;
context = loadContext();

那么线程B就会拿到一个未初始化的content去配置,从而引起错误。

因为这个重排序对于线程A来说是不会影响线程A的正确性的,而如果loadContext()方法被阻塞了,为了增加Cpu的利用率,这个重排序是可能的。

如果要防止重排序,需要使用volatile关键字,volatile关键字可以保证变量的操作是不会被重排序的。

END

Java面试题专栏

【61期】MySQL行锁和表锁的含义及区别(MySQL面试第四弹)

【62期】解释一下MySQL中内连接,外连接等的区别(MySQL面试第五弹)

【63期】谈谈MySQL 索引,B+树原理,以及建索引的几大原则(MySQL面试第六弹)

【64期】MySQL 服务占用cpu 100%,如何排查问题? (MySQL面试第七弹)

【65期】Spring的IOC是啥?有什么好处?

【66期】Java容器面试题:谈谈你对 HashMap 的理解

【67期】谈谈ConcurrentHashMap是如何保证线程安全的?

【68期】面试官:对并发熟悉吗?说说Synchronized及实现原理

【69期】面试官:对并发熟悉吗?谈谈线程间的协作(wait/notify/sleep/yield/join)

【70期】面试官:对并发熟悉吗?谈谈对volatile的使用及其原理

我知道你 “在看”

面试官:你对多线程熟悉吗,谈谈线程安全中的原子性,有序性和可见性?相关推荐

  1. 【74期】面试官:对多线程熟悉吗,来谈谈线程池的好处?

    程序员的成长之路 互联网/程序员/技术/资料共享 关注 阅读本文大概需要 6.5 分钟. 来自:blog.csdn.net/fengye454545/article/details/79536986 ...

  2. treemap怎么保证有序_你对多线程熟悉吗,谈谈线程安全中的原子性,有序性和可见性?...

    作者:a60782885 blog.csdn.net/a60782885/article/details/77803757 注,本篇只是解析基本概念,用作面试应答,非深入 对于Java并发编程,一般来 ...

  3. 面试官说让人事与我谈谈_让我们来谈谈机器人宝贝

    面试官说让人事与我谈谈 and how humans lost. 以及人类如何迷失. None of this is real. It's 21st century disinformation wa ...

  4. 面试官:你说你熟悉jvm?那你讲一下并发的可达性分析

    上面这张图是我还是北漂的时候,在鼓楼附近的胡同里面拍的. 那天刚刚下完雨,路过这个地方的时候,一瞬间就被这五颜六色的门板和自行车给吸引了,于是拍下了这张图片.看到这张图片的时候我就很开心,多鲜活.多舒 ...

  5. 引用计数器法 可达性分析算法_面试官:你说你熟悉jvm?那你讲一下并发的可达性分析...

    持续输出原创文章,点击蓝字关注我吧 上面这张图是我还是北漂的时候,在鼓楼附近的胡同里面拍的. 那天刚刚下完雨,路过这个地方的时候,一瞬间就被这五颜六色的门板和自行车给吸引了,于是拍下了这张图片.看到这 ...

  6. 如何查找历史线程阻塞原因_吊打面试官!Java多线程并发 108 道题,你能答对多少?...

    多线程并发108题 1.Java中实现多线程有几种方法 2.继承Thread 类 3.实现Runnable 接口. 4.ExecutorService. Callable. Future 有返回值线程 ...

  7. threadlocal存连接对象的目的_面试官:知道ThreadLocal嘛?谈谈你对它的理解?

    在java的多线程模块中,ThreadLocal是经常被提问到的一个知识点,提问的方式有很多种,可能是循序渐进也可能是就像我的题目那样,因此只有理解透彻了,不管怎么问,都能游刃有余. 这篇文章主要从以 ...

  8. 安卓开发者中心!那些BAT大厂的Android面试官到底在想些什么?持续更新中

    最近很多人说,Android越来越不好找工作了,学习NDK开发会不会好点,今天就聊聊这个问题.是否应该选择学NDK? 1.哪些场景下要用到NDK开发? 跨平台的库,如FFmpeg, skip,weex ...

  9. 为什么线程池里的方法会执行两次_面试官问你java都有哪些线程池,自己是否自定义过线程池...

    我还记得大学实习面试时,被问到什么是线程池这个问题,因为这个题我被录取了,原因就是我背出来了,而另外一个面试的没背出来,说实话当时还真不知道它是干什么的,就是看面试题给背下来了,在之后就是在实际开发中 ...

最新文章

  1. 2018年04月26日交的智商税
  2. php判断字符串是否为IP,php 判断IP为有效IP地址的方法
  3. 按键精灵脚本 php,HTML_按键精灵 脚本-学习VBS的一个不错的教程,今天我就从总体上对VBS进行介 - phpStudy...
  4. hbase过滤器查询
  5. c语言函数的三种调用方式是什么?
  6. 如何做科研20171206
  7. 海报PSD分层促销模板|深层剖析设计套路
  8. 数据质量低该如何解决
  9. opengl 旋转矩阵和纹理坐标相乘_OpenGL-Rotating Points
  10. maven添加ojdbc6.jar包
  11. 【linux学习笔记】Linux网络管理综合项目实训任务书
  12. Spring事务(2)使用Spring事务完成转账小例子
  13. NW.js之基础篇(2)
  14. 苹果手机开发微信公众号 禁止分享时遇到了问题
  15. python中sqrt(4)*sqrt(9)_Python表达式sqrt(4)*sqrt(9)的值为()
  16. 南京高中计算机老师,30个全省第一!南京老师又出名了!
  17. Latex语法学习10:盒子的使用(fbox, tcolorbox, boitee),支持设置颜色和换页
  18. 【OpenGL】绘制一个点
  19. 好好学习天天向上之InfoPath学习系列(一):Form Services与InfoPath初识
  20. 石英晶振的基本原理与电路设计

热门文章

  1. 阿里与网易考拉收购案谈崩?后者股价下跌5.01%
  2. 全系麒麟810+超强夜拍 荣耀9X正式发布:1399元起
  3. 中国移动中国联通中国电信 三家运营商公布首批5G城市名单
  4. 好心酸!三星可折叠屏手机Galaxy Fold下月也无法发货
  5. 印度智能手机市场Q1出货量同比增长7% 小米蝉联榜首
  6. 谷歌测试工程师分享前端性能监控利器Performance
  7. 一种RTP接收和解包的程序
  8. java netty modbus协议接收iot数据
  9. Python文件的读取与写入
  10. html信号动画,HTML5带音效的雷达检测信号动画