使用双重锁定实现读写锁

时间:2013-08-13 11:12:32

标签: java thread-safety atomic double-checked-locking readwritelock

我编写了一个Java ReadWriteLock,其中读者使用双重检查锁定来获取写锁定。这是不安全的(就像具有延迟实例化的DCL一样)?

import java.util.concurrent.atomic.AtomicInteger;

public class DCLRWLock {
    private boolean readerAcquiringWriteLock = false;
    private boolean writerLock = false;
    private AtomicInteger numReaders = new AtomicInteger();

    public void readerAcquire() throws InterruptedException {
        while (!nzAndIncrement(numReaders)) {
            synchronized (this) {
                if (numReaders.get() != 0)
                    continue;
                if (readerAcquiringWriteLock) {
                    do {
                        wait();
                    } while (readerAcquiringWriteLock);
                } else {
                    readerAcquiringWriteLock = true;
                    writerAcquire();
                    readerAcquiringWriteLock = false;
                    assert numReaders.get() == 0;
                    numReaders.set(1);
                    notifyAll();
                    break;
                }
            }
        }
    }

    public void readerRelease() {
        if (numReaders.decrementAndGet() == 0)
            writerRelease();
    }

    public synchronized void writerAcquire() throws InterruptedException {
        while (writerLock)
            wait();
        writerLock = true;
    }

    public synchronized void writerRelease() {
        writerLock = false;
        notifyAll();
    }

    // Atomically:
    // If x is nonzero, increments x and returns true
    // Otherwise returns false
    private static boolean nzAndIncrement(AtomicInteger x) {
        for (;;) {
            int val = x.get();
            if (val == 0)
                return false;
            else if (x.compareAndSet(val, val + 1))
                return true;
        }
    }
}

我知道Java已经有了ReentrantReadWriteLock。我对如何确定哪种形式的DCL安全或不安全的一般问题更感兴趣?

1 个答案:

答案 0 :(得分:5)

当我们假设仅仅因为我们从共享变量读取非空引用时,DCL的不安全就会出现,编写引用的线程的所有写操作都是可见的。换句话说,我们读了一个通过datarace发布的引用,并假设事情会很好。

在你的情况下,你甚至没有数据竞争,而只是一个原子变量的竞争条件。因此,上述非安全性当然不适用于此。