【问题标题】:Java Non Reentrant Lock ImplementationJava不可重入锁实现
【发布时间】:2012-10-25 09:53:03
【问题描述】:

我已经实现了一个不可重入锁。我想知道这是否有任何错误、竞争条件等。我知道必须使用现有库(而不是编写我们自己的库)这一事实,但这只是为了看看我是否正确理解了 java 并发性。感谢您提供任何反馈。

public class MyLock {
private boolean isLocked = false;
private long owner = -1;
private static String TAG = "MyLock: ";

public synchronized void Lock() throws InterruptedException, IllegalStateException {
    if(!isLocked) {
        isLocked = true;
        owner = Thread.currentThread().getId();

    } else {
        if(owner == Thread.currentThread().getId()) {
            throw new IllegalStateException("Lock already acquired. " +
                                            "This lock is not reentrant");
        } else {
            while(isLocked == true) {
                System.out.println(TAG+"Waiting for Lock, Tid = " +
                        Thread.currentThread().getId());
                wait();
            }   
        }
    }
    System.out.println(TAG+"Lock Acquired: Owner = " + owner);
}

public synchronized void Unlock() throws IllegalStateException {
    if(!isLocked || owner != Thread.currentThread().getId()) {
        throw new IllegalStateException("Only Owner can Unlock the lock");
    } else {
        System.out.println(TAG+"Unlocking: Owner = " + owner);
        owner = -1;
        isLocked = false;
        notify();
    }
}

}

【问题讨论】:

  • 经过深思熟虑,决定将 Locks 设为Reetrant。不建议仅仅为了这样做而实施Non-Reetrant锁吗?你背后的思考过程是什么?为什么需要这样的东西?
  • @DarrylMiles:有没有办法将其移至 codereview?或者我应该在 codereview 中创建另一个帖子。
  • @AmitD:stackoverflow.com/questions/187761/… 对租用锁和不可重入锁进行了很好的讨论。
  • 这里是一个简单的评论:Thread.currentThread().getId() 除了监控/记录(或 JMX 来查询信息,这实际上仅对监控/记录有用)外,没有任何用处。删除 getId() 并使用线程本身。提示:getId() 可以被覆盖。

标签: java concurrency synchronization locking mutex


【解决方案1】:

这是 Java 中“标准”/“不可重入”锁的实现,作为 Java 内置 ReentrantLock 的包装器,它简单地防止锁被多次获取。

/**
 * A "non-reentrant" lock, implemented as a wrapper around Java's ReentrantLock.
 *
 */
class StandardLock implements java.util.concurrent.locks.Lock {

    public static class LockAlreadyHeldException extends RuntimeException {}

    private final java.util.concurrent.locks.ReentrantLock mainLock;

    private void checkNotAlreadyHeld() {
        if (mainLock.getHoldCount()!=0) {
            throw new LockAlreadyHeldException();
        }
    }

    public StandardLock() {
        mainLock=new java.util.concurrent.locks.ReentrantLock();
    }

    public StandardLock(boolean fair) {
        mainLock=new java.util.concurrent.locks.ReentrantLock(fair);
    }

    @Override
    public void lock() {
        checkNotAlreadyHeld();
        mainLock.lock();
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        checkNotAlreadyHeld();
        mainLock.lockInterruptibly();
    }

    @Override
    public boolean tryLock() {
        checkNotAlreadyHeld();
        return mainLock.tryLock();
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        checkNotAlreadyHeld();
        return mainLock.tryLock(time, unit);
    }

    @Override
    public void unlock() {
        mainLock.unlock();
    }

    @Override
    public Condition newCondition() {
        return mainLock.newCondition();
    }
}

这种方法的优点是该类实现了 Java 的 Lock 接口,因此附带条件变量以允许创建监视器。监视器对于充分利用锁进行并发编程很重要。

【讨论】:

  • 这如何回答这个问题?
猜你喜欢
  • 2021-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多