java并发编程(一)
java并发编程(一)
引言
多线程的知识点是一个庞大的体现,对此也是一知半解。一直想系统的深入的学习多线程的知识,奈何一直没有找到机会,好吧,其实就是懒。最近在项目中接触到一个多并发的项目,在项目中踩了无数的坑。在此下定决心做一个并发的学习笔记。
为什么并发会有安全问题
当两个线程同时对一个共享可变变量进行操作时,例如:
两个线程对变量i=1同时执行i++操作。执行完毕后i可能并不等于3而是等于2。因为i++不是原子性的操作,i++实际上是有三个步骤
第一步:读取,从主内存中将i=1读取到本地内存中。
第二步:修改,i自增。
第三部:写入,将i=2写会到缓存中。
所以当两个线程同时将i读取到工作内存中,并分别将变量i赋值为2。
原子性
原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败,有着“同生共死”的感觉。及时在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程所干扰。
可见性
可见性是指当一个线程修改了共享变量后,其他线程能够立即得知这个修改。为什么要这样说?难道一个线程修改了共享变量其他线程不一定会立即得知这个变量的修改?没错事实确实如此。
简单的举一个例子。
在这里插入图片描述
数据 i 是存储在主内存中的,当一个线程执行 i++ 操作的时候首先将 i 从主内存读取到自己线程的工作内存中(也就是缓冲行),然后将工作内存的 i 执行+1操作。如果是单线程程序,在没有其他写入操作的情况下读取这个值,首先会读取缓冲行,缓存命中。那么总能得到 +1 操作之后的值。
但是多线程环境结果则会违背我们的直觉。
由于操作系统的执行,我们并不知道工作内存中的值何时才能被写入到主内存中(理由很简单,我们不可能每次修改了缓存,操作系统就会将值瞬间刷入到主内存吧?这样效率会多低呀)。所以如果这之前另一个线程从主内存读取 i 的值到本地工作内存中。那么他可能并不会感知到另一个线程其实已经修改了 i 的值。
为什么synchronized和volatile可以实现可见性我们在后续会继续介绍。
如何避免并发问题
1.不在线程之间共享该状态变量。
2.将状态变量修改为不可变的变量。
3.在访问状态变量时使用同步。
Synchronized
在多线程并发中synchronized一直是元老级别的角色。利用synchronized来实现同步具体有一下三种表现形式:
对于普通的同步方法,锁是当前实例对象。
对于静态同步方法,锁是当前类的class对象。
对于同步方法块,锁是synchronized括号里配置的对象。
当一个代码,方法或者类被synchronized修饰以后。当一个线程试图访问同步代码块的时候,它首先必须得到锁,退出或抛出异常的时候必须释放锁。那么这样做有什么好处呢?
它主要确保多个线程在同一时刻,只能有一个线程处于方法或者同步块中,它保证了线程对变量的可见性和排他性。
int i = 1;
public sychronized void increment(){
i++;
}
在前面介绍过i++并不是原子操作,所有当多个线程同时操作i++的时候可能会出现多线程并发问题。而上诉代码块中i++是在synchronized修饰的方法中。其中一个线程进入该方法首先获得当前实例对象的锁,当另一个线程试图执行该方法的时候,由于前一个线程并没有执行完毕释放掉锁,所以该线程挂起等待锁的释放。
通过加锁的方式我们实现了将i++非原子操作的方法变成了原子操作的方法。从而实现了排他性。
如下图所示,一个普通的方法会有一个左右摆动的开关,可以连接到任意一个线程,如果该方法不是原子性的,那么可能方法并没有执行完毕就会链接到另一个方法。而被synchronized修饰的方法,链接到一个线程后,除非这个线程将方法执行完毕或者抛出异常,开关才会链接至别的线程。就这样将一个并行的操作变了穿行
帮你买吧
无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。
实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
Synchronized的原理
synchronized用的锁是存在java对象头里的。
锁一共有4个状态,级别从低到高依次是:无所状态、偏向锁状态、轻量级锁状态和重量级锁状态。对于这四种状态《java并发编程艺术》讲解的特别好,有兴趣可以看看这本书的介绍。
总体来说,通过对象头存储的记录指针,互斥指正,标志位等信息来说明当前是对象是被某个线程所使用的,此时别的线程想要获取这把锁要么cas自旋要么线程阻塞。
原文地址https://www.cnblogs.com/zhxiansheng/p/10611994.html
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
好程序员Web前端开发入门之网页制作三要素
Web前端开发是由网页制作演变而来的,主要由HTML、CSS、JavaScript三大要素组成。专业的Web前端开发入门知识也一定会包含这些内容,今天好程序员就给大家简单介绍一下。HTML,超文本标记语言,标准通用标记语言下的一个应用。包括“头”部分(英语:Head)、和“主体”部分(英语:Body),其中“头”部提供关于网页的信息,“主体”部分提供网页的具体内容。CSS,层叠样式表,是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。JavaScript,一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能。随着互联网时代的飞速发展以及企业需求变更,前端开发技术的三要素也演变成现今的HTML5、CSS3、jQuery。因此很多Web前端开发入门课程中的内容也有了一定的调整。HTML5是超文本标记语言的第五次重大修改,在HTML的基础上引进了新的...
- 下一篇
书籍:Data Cleaning数据清洗-基于shell和python - 2018.pdf
简介 作为最畅销的口袋入门系列的一部分,本书旨在为程序员提供足够的数据清理知识,以便能够在自己的项目中工作。 它被设计为使用灵活,强大(和免费)的Unix / Linux shell命令和python来执行常见数据清理任务的实用介绍。 本书充满了现实的例子和大量的命令,说明了语法和命令如何协同工作。 带有源代码的伴随文件可从发布者处下载。 参考资料 下载:https://itbooks.pipipan.com/fs/18113597-356868507 python测试开发项目实战-目录 本文涉及的python测试开发库 谢谢点赞! 本文相关海量书籍下载 2018最佳人工智能机器学习工具书及下载(持续更新) Format Pdf Page Count 188 Pages
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- MySQL8.0.19开启GTID主从同步CentOS8
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池