java多线程之互斥与同步 总结java多线程之互斥与同步解决方案(IT技术) |
您所在的位置:网站首页 › 多线程的同步和互斥 › java多线程之互斥与同步 总结java多线程之互斥与同步解决方案(IT技术) |
想了解总结java多线程之互斥与同步解决方案的相关内容吗,DaHuangXiao在本文为您仔细讲解java多线程之互斥与同步的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:java多线程互斥,java多线程同步,下面大家一起来学习吧。
一、线程互斥与同步
互斥:指的是多个线程不能同时访问共享变量 同步:指的是多个线程按指定的顺序执行操作 在同时有多个线程运行过程中,如何达到互斥和同步呢? 加锁即可在此使用黑马笔记中room例子来说明锁。(ps: 以前就了解锁,但总会记乱,发现使用形象化记忆后就很清楚) 解决互斥 锁就相当于上图的房子,里面放着会被并发访问的共享变量 此时绿色区域(owner)无线程,此时多个线程想并发访问房子里的共享变量,那么只允许其中一个线程进入房子访问,并把房门锁上。 剩下的没有拿到锁的线程只能在entrylist中排队 owner中的线程访问结束后会离开房子,并告诉entrylist的线程可以进房子了 entrylist的线程开始新一轮的挣锁,如此反复 这样就能解决互斥的问题解决同步 (这涉及到为什么wait(),notify()方法需要用锁,就是因为只有用了锁才能完成同步,那么怎么完成的呢?) 多个线程同时启动,如果希望B线程在A线程之后执行 那么当B先抢到锁,即先进入了房子,此时A只能在entrylist中排队 为了让A先执行,那么可以先让B进入蓝色区域,即waitset中等待,并且把门打开,告诉entrylist中的线程可以进来了 那么A进来后,执行完任务,临走时通知waitset中的B,B再回到绿色区域执行任务就能保证有序了 这样就能解决同步问题那么room这个数据结构其实就是synchronized的核心了,接下来总结synchronized原理的时候会一直用room的例子 二、synchronized很多人对synchronized原理的理解也就停留在知道字节码有个monitor关键字来管理锁,再浅一点的只知道怎么用,再者懂得深一点的却记不住。我之前就是想深入了解一下但觉得苦涩,就看不下去了,看了黑马的笔记我觉得这玩意儿其实很简单,所以好的老师还是比较重要的。那么在此我也记录一下怎么更好的去理解synchronized的底层原理 从字节码我们可以知道synchronized的底层就是关联了一个monitor,那么这玩意儿是个什么东西,怎么实现锁的功能呢? 首先,可以把monitor的数据结构简化成上图的room,具体点描述如下图 以上就是synchronized的原理。有人就会问了,你说的这些文字我都懂啊,搞个图摆在这也没啥用。 接下来我将从上图直接回答下面的常见的问题 wait()和notify()为什么都得在synchronized后使用? wait()就是将线程放入waitset中,那么waitset是在room里面的,不上锁怎么能进room中?同理,不进入room,在门外怎么使用notify()怎么能叫醒waitset中的线程?wait()会释放锁吗? 废话,不开门的话,怎么放线程进来,就更别提唤醒了notifyALL()为什么不会唤醒其他锁对象的线程? 进哪个room才能叫哪个waitset,进了Aroom当然只能叫醒A的waiset了说说synchronized的原理? 把图画出来就行了线程什么时候从runnable变成waiting,什么时候变成block? 看图,进入waiset就是wait,所以调wait()就变成waiting状态进入entrylist就是block,所以被唤醒后以及没抢到锁都变block 。。。。。。。。。。。。注意了,这里涉及monitor的原理都是synchronized最根本的原理,也称重量级锁,可以看到monitor会频繁切换线程状态,效率比较低。后来synchronized改进了,在使用monitor前还有好几种方案,分别为偏向锁,轻量锁,以及自旋优化。这部分也是面试常考点,也容易记乱,但用图例去记就很清楚。 那么接下来就说说synchronized的改进 三、轻量锁与偏向锁轻量锁与偏向锁的核心都是先不让线程冲突的时候直接去找monitor,而是先用锁对象的对象头字段来解决冲突 (写博客好累啊。。。算了我就总结一些自己觉得关键的地方吧) 轻量锁 对于轻量锁而言,每个线程维护了一个锁记录,抢占锁的过程就是用CAS将自己的信息与锁对象的对象头mark word部分交换 这样其他慢一步的线程CAS会失败,就意识到锁已经被占了 可重入只需要在占锁的时候判断锁对象的markword记录的是不是自己的线程id即可,是的话就能够获取锁,也就是叠加一个锁记录 释放锁就意味着删除锁记录,直到锁记录清空,就将锁对象头部被修改的字段变回原样 轻量锁是认为不会有竞争,如果发生了线程竞争,锁需要升级,不然上述方法没有像monitor的entrylist来管理其他竞争暂时没拿到锁的线程 锁升级就是锁膨胀,直接调monitor来管理,就将owner指向当前线程,然后竞争线程去entrylist排队 其中涉及自旋优化,就是线程竞争时,第二个线程不用立刻去entrylist中,这样又要涉及上下文切换,可以自旋一会看锁能否抢到偏向锁 轻量锁每次占锁都要用一次CAS来更新锁对象头,如果本来就没啥竞争那CAS就是无用的操作了 为了解决这个问题,线程抢锁成功后直接把自己的ID刻在锁对象头中,需要判断重入时只需判断ID是否相同即可 相关文章Java多线程同步器详解 Java多线程同步器代码详解Java多线程同步问题 以银行取钱为例模拟Java多线程同步问题完整代码Java多线程同步synchronized 浅析Java多线程同步synchronizedJava多线程同步 五种Java多线程同步的方法Vue项目优化 Vue项目优化的一些实战策略高并发核心Selector Java进阶之高并发核心Selector |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |