这篇文章将为大家详细讲解有关怎么在java中实现多线程的互斥与同步,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
一、线程互斥与同步
互斥:指的是多个线程不能同时访问共享变量
同步:指的是多个线程按指定的顺序执行操作
在同时有多个线程运行过程中,如何达到互斥和同步呢?
- <李>
加锁即可
李>在此使用黑马笔记中房间的例子来说明锁。(ps:以前就了解锁,但总会记乱,发现使用形象化记忆后就很清楚)
解决互斥
- <李>
锁就相当于上图的房子,里面放着会被并发访问的共享变量
李> <李>此时绿色区域(所有者)无线程,此时多个线程想并发访问房子里的共享变量,那么只允许其中一个线程进入房子访问,并把房门锁上。
李> <李>剩下的没有拿到锁的线程只能在entrylist中排队
李> <李>中所有者的线程访问结束后会离开房子,并告诉entrylist的线程可以进房子了
李> <李>entrylist的线程开始新一轮的挣锁,如此反复
李> <李>这样就能解决互斥的问题
李>解决同步
(这涉及到为什么等(),通知()方法需要用锁,就是因为只有用了锁才能完成同步,那么怎么完成的呢?)
多个线程同时启动,如果希望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(锁对象)的时候,相当于让锁对象绑定了一个monitor(具体绑定方法不打算在后面总结)
那么多个线程中方法涉及到该锁对象时,都会来访问锁对象对应的monitor
此时线程thread-2抢到了锁,操作就是让monitor中的owner字段指向thread-2线程,意味着当前线程获取到了基于该monitor的锁
其他没抢到锁的,monitor会将他们放在Entrylist中等待,这些线程只能在队列中等着
thread-2线程完成操作后就会退出,并通知entrylist的线程重新抢锁
如果在执行过程中,线程调用了wait()方法,monitor就会将他们放入waitset中等待别人唤醒
(看回room结构)owner进入waitset后会把门打开,让entrylist的线程进来
直到某时刻owner中有线程调用notify()方法,waitset中的线程才会被唤醒,唤醒后会进入entrylist中重新抢锁
以上就是synchronized的原理。有人就会问了,你说的这些文字我都懂啊,搞个图摆在这也没啥用。
接下来我将从上图直接回答下面的常见的问题
wait()和notify()为什么都得在synchronized后使用?
wait()就是将线程放入waitset中,那么waitset是在room里面的,不上锁怎么能进room中?同理,不进入room,在门外怎么使用notify()怎么能叫醒waitset中的线程?
wait()会释放锁吗?
废话,不开门的话,怎么放线程进来,就更别提唤醒了
怎么在java中实现多线程的互斥与同步