ReentrantLock的实现:
public class ReentrantLock {
private boolean isLocked = false;
private Thread lockedBy = null;
private int lockCount = 0;
public synchronized void lock() throws InterruptedException{
while(isLocked && Thread.currentThread() != lockedBy){
this.wait();
}
isLocked = true;
lockedBy = Thread.currentThread();
lockCount++;
}
public synchronized void unlock(){
if(Thread.currentThread() == lockedBy){
lockCount--;
}
if(lockCount == 0){
isLocked = false;
this.notify();
}
}
}发布于 2015-07-21 11:45:20
您的代码看起来很合理,除了两个例外,解锁应该只在锁被解锁时通知.您的代码当前允许不对称通知(过多通知)。
考虑:
公共同步无效解锁(){ if(Thread.currentThread() == lockedBy){ lockCount-;} if(lockCount == 0){ isLocked = false;this.notify();}
即使没有任何东西锁定,上面的代码也会发出通知。这一效果可能很小,但重要的是这类类要表现出对称性。守则应是:
public synchronized void unlock(){
if (!isLocked || lockedBy != Thread.currentThread()) {
return;
}
lockCount--;
if(lockCount == 0){
isLocked = false;
this.notify();
}
}另一个漏洞是您泄露了锁的监视器。使用同步方法是一个问题,因为有人可以简单地对整个类进行同步,并将整个系统死锁.考虑一条恶意的线程:
synchronized (lockInstance) {
Thread.sleep(10000000);
}现在没有其他线程能够锁定或解锁该实例,并且只会挂起。
您应该使用私有监视器:
private final Object sync = new Object();然后同步处理:
synchronized (sync) {
.....
}发布于 2015-11-02 18:48:35
您还可以去掉isLocked实例变量,并将表达式isLocked替换为lockedBy != null。
结合@rofl的建议,我得出以下结论:
class ReentrantLock {
private final Object sync = new Object(); // private monitor
private Thread lockedBy = null; // null => unlocked
private int lockCount = 0;
public void lock() throws InterruptedException {
synchronized (sync) {
Thread callingThread = Thread.currentThread();
while (lockedBy != null && lockedBy != callingThread)
wait();
lockedBy = callingThread; // (re)locked!
lockCount++;
}
}
public void unlock() {
synchronized (sync) {
if (Thread.currentThread() == lockedBy)
if (--lockCount == 0) {
lockedBy = null; // unlocked!
notify();
}
}
}
}https://codereview.stackexchange.com/questions/97568
复制相似问题