java 并_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自旋要么线程阻塞。
java 并_java并发编程(一)相关推荐
- java赋值语句_java并发编程之原子性问题
程序是否线程安全,取决于哪些要素呢,主要是以下三个: 原子性, 可见性, 有序性. 今天先一起来学习原子性. 原子性: 我理解一个操作不可再分,即为原子性.而在并发编程的环境中,原子性的含义就是只要该 ...
- java 可见性_Java并发编程-volatile可见性详解
前言 要学习好Java的多线程,就一定得对volatile关键字的作用机制了熟于胸.最近博主看了大量关于volatile的相关博客,对其有了一点初步的理解和认识,下面通过自己的话叙述整理一遍. 有什么 ...
- 《Java线程与并发编程实践》—— 2.3 谨防活跃性问题
本节书摘来异步社区<Java线程与并发编程实践>一书中的第2章,第2.3节,作者: [美]Jeff Friesen,更多章节内容可以访问云栖社区"异步社区"公众号查看. ...
- Java增强之并发编程
Java增强之并发编程 1 多线程 1.1 进程及线程 程序启动的时候,电脑会把这个程序加载到内存,在内存中需要给当前的程序分配一段的独立运行的空间,这个空间就专门负责这个程序的运行.每个应用程序运行 ...
- Java零基础并发编程入门
Java零基础并发编程入门 并发编程主要包括: 线程,同步,future,锁,fork/join, volatile,信号量,cas(原子性,可见性,顺序一致性),临界性,分布式 了解基础: JMM: ...
- java书籍_还搞不定Java多线程和并发编程面试题?你可能需要这一份书单!
点击蓝色"程序员书单"关注我哟 加个"星标",每天带你读好书! 在介绍本书单之前,我想先问一下各位读者,你们之前对于Java并发编程的了解有多少呢.经过了1 ...
- 《Java线程与并发编程实践》—— 2.6 小结
本节书摘来异步社区<Java线程与并发编程实践>一书中的第2章,第2.6节,作者: [美]Jeff Friesen,更多章节内容可以访问云栖社区"异步社区"公众号查看. ...
- 《Java线程与并发编程实践》—— 1.2 操作更高级的线程任务
本节书摘来异步社区<Java线程与并发编程实践>一书中的第1章,第1.2节,作者: [美]Jeff Friesen,更多章节内容可以访问云栖社区"异步社区"公众号查看. ...
- 厚积薄发打卡Day26:狂神说Java之JUC并发编程<代码+笔记>(上)
前言: 学习视频来源:[狂神说Java]JUC并发编程最新版通俗易懂 一个十分优秀且励志的技术大牛+Java讲师,十分推荐他的频道:遇见狂神说
最新文章
- 赠书 | AI 还原宋代皇帝,原来这么帅?!
- EasyUI中Dialog对话框的简单使用
- java项目(java project)如何导入jar包的解决方案列表
- java 雪花特效_java实现图片飘雪花的特效
- 流程流转相关业务与流转的分离
- 初识Activiti
- How to Use Hive-based Registry IN WINCE.NET
- 26个要素,仅仅依靠百度打造成功网站
- mysql字符串比较数字
- [转帖] 启动多个Tomcat 需要修改的端口
- mysql分组取每组前几条记录(排序)
- Smartisan OS ROM 小米手机 2/2S 标准版 刷机教程
- HBase中MVCC的实现机制及应用情况
- Vmware里Ubuntu安装Vmware Tools时提示:客户机操作系统己将 CD-ROM 门锁定,并且可能正在使用 CD-ROM.....
- ojdbc6.jar下载Linux,Linux下 和 Windows 下 Oracle Instant Client 的安装.
- 谷歌ai人工智能叫什么_为Google产品提供动力的人工智能
- CRMEB开源商城部署在腾讯云
- EOS的trace_api_plugin插件测试
- 客2消,客1消,客0消...脉脉劝退客户端多次的你们究竟是何用意?
- 往日学习=【iptables实验part3-搭建简单蜜罐网络】
热门文章
- Docker基础学习笔记02:Docker基本操作
- Top 10 Digital Transformation Trends For 2020
- 【BZOJ2655】calc,dp+拉格朗日插值法
- 人称代词和Be动词的现在简单肯定式_1
- postman socket接口测试_基于postman测试接口(整套接口测试)
- 【英语学习】【WOTD】cacophony 释义/词源/示例
- 信息论与编码_庆祝中山大学计算机科学系成立40周年系列活动 | 第四届“信息论与编码中大论坛”...
- Unity Shader:雾的数学运算以及在Unity中使用Fog
- attributeerror: __enter___python魔法方法之__setattr__()
- 在虚幻引擎 4 中处理内存泄漏问题