前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线程同步

线程同步

作者头像
端碗吹水
发布2020-09-23 10:37:06
6210
发布2020-09-23 10:37:06
举报
文章被收录于专栏:程序猿的大杂烩

线程同步:

线程是独立并行的,许多的线程就像许多的人一样,如果对某样东西进行使用的时候不进行排队,都争抢使用的话就自然容易会导致破坏这样东西。

使用多个线程去对某个值进行操作的时候没有使用同步块或者同步方法,多个线程就会一起操作这个值,数据就会遭到破坏导致结果值是错误的。

代码示例:

c6f4c37c3e553534b6a4144e882a8205.png
c6f4c37c3e553534b6a4144e882a8205.png

运行结果:

68bca0882d4310e7cd04001e1c525e76.png
68bca0882d4310e7cd04001e1c525e76.png

从代码来看本来运行的结果应该是10000的,得出错误的结果是因为每个线程抢着执行,比如第一个线程执行到3999的时候第二个线程就来执行到2999就会覆盖第一个线程计算的值,第三个线程执行到4564又覆盖了第二个线程计算的值,以此类推。最后就会得到错误的结果值。

同步块:

解决上面出现的问题,办法就是令线程同步执行,一个个的去使用资源,能让线程们同步的方法之一就是同步块,同步块参数里的对象必须是唯一的才能起到同步效果,如若不然也是没有同步效果的。

因为这就好比资源是房间,同步块参数里的对象就像是厨房的钥匙,唯一的对象就代表这个钥匙只有一份,所以每个线程都得等上一个线程使用完了把钥匙交给下一个线程,下一个线程才能开启这个房间,上一个线程没有把钥匙交给下一个线程的话,下一个线程是无法进入房间的,这样就起到了每个线程都得排队执行的效果。

  示意图:

e2d36468a8841cf664c797ededeec29f.png
e2d36468a8841cf664c797ededeec29f.png

但是如果同步块参数里的对象不是唯一的,是多个的。那么,就代表着这个钥匙有很多份,这样的话多个线程都能拿到开启房间的钥匙。所以就失去了同步的效果,因为每个线程都不需要排队等上一个线程的钥匙了,没有同步效果最后的执行结果值自然也是错误的。所以必须要需要注意这一点。

  示意图:

bda692a2cfa6f4f183f7ffd596b6ffd4.png
bda692a2cfa6f4f183f7ffd596b6ffd4.png

有同步效果的代码示例:

78be2ae6f5220e1d8b3b13c6b744c946.png
78be2ae6f5220e1d8b3b13c6b744c946.png

运行结果:

3a508f68f4271743e210b99f75def754.png
3a508f68f4271743e210b99f75def754.png

无同步效果的代码示例:

0eb135a9cac3d77d77fd0488457160a1.png
0eb135a9cac3d77d77fd0488457160a1.png

运行结果:

b15819f81a96f6ad392b4b05c08ec903.png
b15819f81a96f6ad392b4b05c08ec903.png

同步块一般是在在编写代码的过程中刚好某一处需要同步效果的时候才写的,如果编写代码的时候提前知道需要同步效果的话,是使用同步方法的。

同步方法:

同步方法就是在方法上加上synchronized同步关键字,要记得的是加上静态关键字,因为不写静态的话线程会同时调用这个这方法,同时调用同一个方法也会失去同步效果。

代码示例:

6e1d2972972870aaccbedb4bc7979c4e.png
6e1d2972972870aaccbedb4bc7979c4e.png
64403f15739e95b5b98297b7b557080b.png
64403f15739e95b5b98297b7b557080b.png

运行结果:

a3ddf51b8852466d88b05accaa8528c5.png
a3ddf51b8852466d88b05accaa8528c5.png

线程死锁:

线程死锁就是两个线程的同步方法交叉访问就会形成死锁,就是两个线程互相死等对方执行完。

示意图:

23f570a57509ea6c49b1345bd4811611.png
23f570a57509ea6c49b1345bd4811611.png

代码示例:

74c63b38335d9a1a6fed8d922ff91a83.png
74c63b38335d9a1a6fed8d922ff91a83.png
05d6ff47b3e355cf192def78fde4fde4.png
05d6ff47b3e355cf192def78fde4fde4.png

一般出现死锁的情况很少,而且在jdk的飞行器里也可以检测出死锁,所以只是需要了解这一情况的发生原理即可。

使用飞行器检测线程死锁:

首先打开飞行器进入到当前的工程中:

a334706bd94ba83911ae6ba0c0568500.png
a334706bd94ba83911ae6ba0c0568500.png

然后进入线程选项:

6236924ac61d1131a9e3680372f343ea.png
6236924ac61d1131a9e3680372f343ea.png

将死锁检测打上勾:

540092927c4042ac9a3497db5352b408.png
540092927c4042ac9a3497db5352b408.png

然后就可以查看死锁哪一列是否存在死锁了:

8eb03a424cb2ae99656212572626b49e.png
8eb03a424cb2ae99656212572626b49e.png
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017/10/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档