java - 如果 ReentrantLock 已锁定,则等待但不锁定该锁

标签 java multithreading reentrantlock

我的代码中有一个 ReentrantLock,并且想用它每秒清除一次数组;我不希望其他线程在清除数组时更改数组,但如果我当前没有清除数组,其他线程不必等待,如下所示:

public void addToArray(Object a) {
    lock.waitforunlock(); //not a real method just to clarify my intentions
    array.add(a);
}

为了更好地阐明我的意图,我将解释这个过程:netty eventloop 将调用我的网络处理程序,然后该网络处理程序将调用之前的 addToArray 方法,每秒一次,我的主线程将永远不会是 Netty 线程将被清除数组,此时每个netty线程都必须等待直到完成!注意:addToArray 方法是线程安全的,我不想同步它,因为这样事件循环的漏洞点就没用了。

最佳答案

没有任何 API 方法可以完全满足您的要求。

最有效的方法是这样的:

try {
    lock.lock();
} finally {
    lock.unlock();
}

换句话说,暂时捕获锁然后释放它。

但是问题来了。

  1. 一般来说,在您释放锁的那一刻,其他线程可能会立即获取它。因此,您的 array.add() 调用可能会与其他线程对 array 执行操作同时发生。即使您的用例意味着另一个线程获取锁的可能性极小,它仍然可能发生;例如如果您的服务器负载严重,当前线程在释放锁后立即被抢占。

  2. 大概您正在 array.add() 中执行内存写入。除非通过适当的同步来执行,否则这些更新可能对其他线程不可见。 (你说“addToArray 方法是线程安全的”,但是如果没有清晰、详细地解释你的意思,我会不愿意说这个代码是线程安全的。 )

  3. 如果您在此处尝试执行的是在发生其他事情后 array.add() ,那么测试锁/等待它被释放不会告诉您如果事件真的发生了。它只是告诉您,这并不是在测试成功的那一刻发生的。

简而言之,我怀疑在进行更新之前等待锁被释放实际上是一个正确的解决方案......无论您如何实现等待。


另一种看待这个问题的方式。

  • 如果array.add()是完全线程安全的,并且无论其他线程是否持有锁都可以正常工作,为什么您需要来测试锁?只需调用该方法即可。

  • 如果您实际上尝试在某个与释放锁同时发生的事件之后发生 array.add() 调用,请使用循环屏障或类似的方法。


注意:我阅读并试图理解您的解释,但我对您所说的内容感到困惑。我认为是由于“语言问题”。

关于java - 如果 ReentrantLock 已锁定,则等待但不锁定该锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49695996/

相关文章:

java - JAI 渲染操作 : Check for corrupt image without rendering

java - 如何使用 JSNI 从 GWT Java 运行 JavaScript 函数?

java - Java 正则表达式中的 Pattern.UNIX_LINES

java - 在java的内存游戏中保持2张图片打开一段时间

java - 为 CopyOnWriteArrayList 中的添加操作获取锁

java - 可重入锁 - 尝试使用 rxtx 将 byte[] 写入串行端口时出现非法监视器状态异常

java - android 将变量从一种方法传递到另一种方法

multithreading - CoreFoundation : Receive/process notifications in background thread

生产者消费者上的Java多线程

java - 对象与条件,wait() 与 await()