Java中是否有带有监听器的读写锁?

5

有没有一个Java库实现了类似于ReadWriteLock的行为,但使用监听器或CompletableFuture/CompletionStage而不是阻塞?

理想情况下,我想这样编写:

lock = ...

CompletionStage stage = lock.lockRead();
stage.thenAccept(r -> { doSomething(); r.release(); });

同时也很重要:

CompletionStage stage = lock.tryLockWrite(10, TimeUnit.SECONDS);
stage.handle(callback);

我想了解这样的东西是否存在,若存在,它被称为什么

我不打算自己实现,而是希望使用一个库来简化一些框架代码。


这是带有lambda表达式的java-8,对吗? - Andremoniy
没错,但我不是在问Lambda表达式。然而,CompletionStage仅在Java 8中可用。 - Daniel Sperry
那个带有CompletableFuture的ReadWriteLock的语义是什么?CompletableFutures处理程序由另一个线程在未来的某个时间调用。您是否意味着在另一个线程中扩展读取锁定,直到该处理程序完成,以重新获取完成时的锁定,或者在完成期间不使用任何锁定? - meriton
等等,你想要一个非阻塞锁?根据定义,获取锁必须阻塞直到它可用,所以不能是非阻塞的。 - meriton
关于“锁”。是的,这很有道理,这就是为什么我写了“像某物一样行为”的原因,我不确定“Lock”名称是否适合在那里。然而,MT语义对我来说似乎很清楚。您请求锁定(访问资源)。您得到它。您必须释放它。唯一的问题是它可以在一个或多个线程中发生。 - Daniel Sperry
1个回答

2

我认为自己写代码并不会太难。很可能比寻找一个库要花费更少的时间。总体而言,它非常简单:

static const int STATE_UNLOCKED = 0;
static const int STATE_READING = 1;
static const int STATE_WRITING = 2;
int state = STATE_UNLOCKED;
int readers = 0;
Queue<CompletableFuture<Void>> queueWriters = new LinkedList<CompletableFuture<Void>>();
Queue<CompletableFuture<Void>> queueReaders = new LinkedList<CompletableFuture<Void>>();

public synchronized CompletionStage<Void> lockWriter() {
    CompletableFuture<Void> l = new CompletableFuture<Void>();
    if (state == STATE_UNLOCKED) {
        state = STATE_WRITING;
        l.complete(null);
        return l;
    }
    queueWriters.offer(l);
    return l;
}

public synchronized CompletionStage<Void> lockReader() {
    CompletableFuture<Void> l = new CompletableFuture<Void>();
    if (state != STATE_WRITING) {
        state = STATE_READING;
        readers++;
        l.complete(null);
        return l;
    }
    queueReaders.offer(l);
    return l;
}

public void unlock() {
    CompletableFuture<Void> l = null;
    synchronized(this) {
        if (state == STATE_READING) {
            readers--;
            if (readers > 0) {
                return;
            }
        }
        l = queueReaders.poll();
        if (l != null) {
            state = STATE_READING;
            readers++;
        }
        else {
            l = queueWriters.poll();
            if (l != null) {
                state = STATE_WRITING;
            }
            else {
                state = STATE_UNLOCKED;
                return;
            }
        }
    }
    l.complete(null);
    while (true) {
        synchronized (this) {
            if (state != STATE_READING) {
                return;
            }
            l = queueReaders.poll();
            if (l == null) {
                return;
            }
            readers++;
        }
        l.complete(null);
    }
}

在上述内容中添加定时锁定(可以使用某种“到期队列”或者通过防止在queueWriters不为空的情况下执行其他读取器来预防写入饥饿),这也不应该太难。


所以,我用类似这样的方法解决了我的问题。但是我正在寻找一个具有Doug Lea级别质量的库。 - Daniel Sperry
1
说到 Promise/async,使用队列几乎没有更好的解决方案了。你不能像自旋锁一样没有等价数量的线程运行。如果你足够努力地搜索,可能会找到一些预打包的东西,但不一定比这个“更好”。我实现中可以改进的一件事是,在“lockReader”和“lockWriter”中调用“complete”的同步块内发生。或者,如果保证单线程操作(事件循环?),你可以完全跳过同步。 - SlugFiller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接