这次讲讲ReentrantLock。这个锁的出现,就是为了要解决Sychronized的问题。
Synchronized是一个一刀切的锁。
而真实的并发场景很多很细。比如Synchronized是一个线程必须等待在那儿的锁,而不能控制说如果碰到锁我就不干了,我绕开的场景。另外,对资源纯读,和对资源修改,也会碰到不一样的并发问题。所以,ReentrantLock以及它的子类就是为了细化的目的出现了。
ReentrantLock的意思是可重入,所以,在同一个线程中,可以多次进入lock,线程内又是同一个锁,不会打架的嘛。但跨线程就不可入,这和Sychronized就一样了,这是锁本质。
那么ReentrantLock如何实现wait和notify的功能?
先回顾下Synchronized中的wait和notify会发生什么?wait会阻塞本线程,并释放锁,于是在锁对象上排队的其他线程可以去争抢锁,干活了。notify则会随机通知一个wait线程可以干活了。
ReentrantLock中也是类似。它会通过Condition对象来实现。Condition有两个方法,一个叫await,一个叫signal,分别对应wait和notify。
那么ReentrantLock的细粒度体现在哪里呢。
首先看lock()方法。除了lock以外,还有tryLock,和lockInterruptibly。
lock()的效果和Synchronized一致。没获得锁会阻塞,直到获得锁。
trylock(),会立刻去获得锁。但无论是否获得,都会立刻返回一个bool值。可以写在一个if块中,获得锁……没获得锁……
lockInterupptibly(),则是一个可中断地获得锁。啥叫可中断地获得锁,太诡异了。中断又是另一个复杂的事儿。
好,讲中断。
我们要先想线程是咋停止的。stop吗?stop已经停用了。因为stop太简单暴力。
所以要用interupt方法。他比stop柔和些,它只是标记一下这个线程现在需要interupt了。标记之后,线程内部会根据这个interupt的标记做什么处理,就看线程怎么写了。
中断就讲完了,挺简单的吧。
那lockInterupptibly(),以及所有带Interupptibly这样的方法,都是会在内部判断一下当前的中断状态。如果中断,就会throw一个中断异常,也就是终止了线程。在终止前,我们还可以去try……catch……做一些处理。
网友评论