现在终于有一次学习到了锁机制,上次学习还是在学习java基础的时候遇到的,当时对于锁还只是停留在一个大致的了解上,这次是彻底的深入学习,我在学习中遇到的第一个我认为的难点就是可重入锁。我一开始想要像大多数人那样宽泛的理解:自家开门后房屋任进。后来发现这样理解有不少问题,大大忽略了锁的概念和可重入锁在这样的问题中扮演的角色。
可重入锁,就是当一个类中多个方法上锁,当多个方法中嵌套调用了上锁的方法,拿到第一把锁的线程在进入其他上锁方法时,无需在次获得锁。
这样的概念对我来说理解起来十分容易,但那是我没有仔细的推敲,如果不可重入锁遇到了两个加锁的方法,相比于可重入锁,会有什么问题?
会遇到死锁问题。我之前一直以为死锁只有两条线程同时操作的时候才会遇见,没想到不可重入锁会以这种方式让我更新了认识。假设一个类中有两个加上不可重入锁的方法A和方法B,方法A中调用了方法B。此时线程X争抢到了线程执行权,拿到了锁进入了方法A,此时A方法上锁,锁的状态修改权在A方法中,而线程X向下执行,进入方法B,此时锁在方法A中,锁的操作权限也在方法A中,B方法由于无法操作锁,进入了堵塞状态,而A方法又必须等待B方法执行完才能向下执行从而操作锁。这就会形成死锁问题。
方法A:你为什么不执行啊?!
方法B:因为我没拿到锁啊!
方法A:那你去拿锁啊?!
方法B:我执行完才能拿到锁啊!
方法A:那你执行完啊?!
方法B:???
而可重入锁就可以避免这个问题,他除了线程需要有执行权外,还可以识别线程是否是拥有锁的线程,也就是身份认证。继续以上述所讲为例,当线程X进入方法A时,拿到了锁,对于锁有执行权,可以释放锁,但是当线程进入方法B后,线程X并没有锁,失去执行权的他无法修改锁的状态,但本该因此进入自旋(cas乐观锁),或者wait等待状态的线程X因为可重入锁的识别身份功能,让他跳过了自旋或wait,直接获取了锁执行权。这就是可重入锁。至于身份认证就比较容易了,只要比对当前线程对象和锁拥有者是否是同一个对象即可。