简体   繁体   English

通过双重检查锁定实现读写锁定

[英]Implementing Read-Write Locks with Double-Checked Locking

I've written a Java ReadWriteLock where the readers use double-checked locking to acquire the write-lock. 我已经编写了Java ReadWriteLock,读者可以使用双重检查的锁定来获取写锁定。 Is this unsafe (as is the case for DCL with lazy-instantiation)? 这是不安全的吗(就像带惰性实例化的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;
        }
    }
}

I know that Java already has a ReentrantReadWriteLock. 我知道Java已经有一个ReentrantReadWriteLock。 I'm more interested in the general question of how to determine what forms of DCL are or aren't safe? 我对如何确定DCL的哪些形式是安全的或不安全的一般问题更感兴趣。

The unsafety of the DCL comes about when we assume that just because we read a non-null reference from a shared variable, all the writes by the thread which wrote the reference will be visible. 当我们假设仅仅因为我们从共享变量中读取了一个非空引用时,DCL的不安全就会出现,所有写该引用的线程的写操作都是可见的。 In other words, we read a reference published via a datarace and assume things will work out fine. 换句话说,我们阅读了通过数据竞赛发布的参考资料,并认为一切正常。

In your case you don't even have a data race, but just a race condition on an atomic variable. 在您的情况下,您甚至没有数据争用,而只是原子变量上的争用条件。 Therefore the non-safety described above certainly does not apply here. 因此,上述非安全性当然不适用于此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM