一、为什么需要锁?
假如有个场景是这样:10个线程共同操作数据i,每个线程都对其做自增操作,那么我们所希望的最终结果是i最后的结果是100,可等到实际操作时却发现,最后的结果不尽人意,偶尔可能运气好,i的结果为100,但是并不是每次都能这么好运。所以我们需要锁来保证我们数据的完整性,通俗点来说,也就是保证每一次自增的操作都被记录上,不会丢失。
二、为啥数据会丢失
要解释这个问题,就需要牵扯到JMM也就是java内存模型 。
当我们代码在执行的时候,实际上是在主内存中开辟了一块内存空间用来保存i,然后每个线程在对i进行操作的时候,会先把i从主内存读取到线程的本地内存中,然后对本地内存中i的副本做操作,操作完成之后再同步到主内存。但是在多线程的情况下,就会出现这样一种情况:线程A和线程B同时读取到了i(假设此时i等于0),并且分别对i做了自增操作,那么此时线程A中i的副本的值为1,线程B中i的副本的值为1,然后它们先后把修改的i的副本同步回主内存,那么此时主内存中的i最终的值就是1,丢失了一次自增操作,导致了数据不完整。
三、如何保证数据不丢失
联想到生活中的实际问题,比如厕所只有一个,那么每次进去上厕所的人只能有一个人,同时为了防止多个人同时进去使用一个厕所,就需要给厕所加个锁,让某个时间段内,厕所只会供一个人单独使用,其他人想使用,必须等厕所没人用了才能进去,同理,我们想要保证数据不丢,也可以套用这个思路
四、锁到底锁住的是什么?
很多人可能下意识的认为那还用说?锁肯定锁住的是需要同步的数据啊,其实这是不太对的,锁更多的是提供了一个权限,只有获得了这个锁的使用权限,我们再才能去做相应的操作,否则就不行,其实程序中锁的概念和生活中钥匙比较接近,你只有拥有了钥匙,你才能开门,才能进屋,否则你就只能被拒之门外。在代码中,锁住的不是一串代码,也不是数据,而是一个对象,谁拥有这个锁对象,谁就拥有了对某段代码的执行权限。