线程同步:
线程是独立并行的,许多的线程就像许多的人一样,如果对某样东西进行使用的时候不进行排队,都争抢使用的话就自然容易会导致破坏这样东西。
使用多个线程去对某个值进行操作的时候没有使用同步块或者同步方法,多个线程就会一起操作这个值,数据就会遭到破坏导致结果值是错误的。
代码示例:
运行结果:
从代码来看本来运行的结果应该是10000的,得出错误的结果是因为每个线程抢着执行,比如第一个线程执行到3999的时候第二个线程就来执行到2999就会覆盖第一个线程计算的值,第三个线程执行到4564又覆盖了第二个线程计算的值,以此类推。最后就会得到错误的结果值。
同步块:
解决上面出现的问题,办法就是令线程同步执行,一个个的去使用资源,能让线程们同步的方法之一就是同步块,同步块参数里的对象必须是唯一的才能起到同步效果,如若不然也是没有同步效果的。
因为这就好比资源是房间,同步块参数里的对象就像是厨房的钥匙,唯一的对象就代表这个钥匙只有一份,所以每个线程都得等上一个线程使用完了把钥匙交给下一个线程,下一个线程才能开启这个房间,上一个线程没有把钥匙交给下一个线程的话,下一个线程是无法进入房间的,这样就起到了每个线程都得排队执行的效果。
示意图:
但是如果同步块参数里的对象不是唯一的,是多个的。那么,就代表着这个钥匙有很多份,这样的话多个线程都能拿到开启房间的钥匙。所以就失去了同步的效果,因为每个线程都不需要排队等上一个线程的钥匙了,没有同步效果最后的执行结果值自然也是错误的。所以必须要需要注意这一点。
示意图:
有同步效果的代码示例:
运行结果:
无同步效果的代码示例:
运行结果:
同步块一般是在在编写代码的过程中刚好某一处需要同步效果的时候才写的,如果编写代码的时候提前知道需要同步效果的话,是使用同步方法的。
同步方法:
同步方法就是在方法上加上synchronized同步关键字,要记得的是加上静态关键字,因为不写静态的话线程会同时调用这个这方法,同时调用同一个方法也会失去同步效果。
代码示例:
运行结果:
线程死锁:
线程死锁就是两个线程的同步方法交叉访问就会形成死锁,就是两个线程互相死等对方执行完。
示意图:
代码示例:
一般出现死锁的情况很少,而且在jdk的飞行器里也可以检测出死锁,所以只是需要了解这一情况的发生原理即可。
使用飞行器检测线程死锁:
首先打开飞行器进入到当前的工程中:
然后进入线程选项:
将死锁检测打上勾:
然后就可以查看死锁哪一列是否存在死锁了: