java - 可以从一个线程转移到另一个线程的锁

标签 java concurrency locking atomic semaphore

我正在寻找一种锁,持有锁的线程可以将其传递给它选择的另一个线程。

这就是我想要它的原因:

  • 我有一个类似于 ConcurrentHashMap 的类 - 一个分为多个段的专门集合
  • 大多数修改只需要锁定一个片段。少数需要锁定两个段(具体来说,修改 key ,使其从一个段移动到另一个段。)
  • 大多数读取不需要锁定 - volatile 读取通常就足够了,但如果修改计数检查失败,偶尔搜索需要一次锁定所有段
  • 搜索在多个线程中完成(通过 ThreadPoolExecutor)
  • 搜索功能必须具有所有段的一致 View (例如,当条目从一个段移动到另一个段时,它不得遗漏一个条目。)
  • 搜索任务(针对单个片段)可能随时中断。

现在我正在考虑在主线程中调用搜索方法并发现它需要锁定所有段的情况。主线程必须立即持有所有段锁(以确保没有干扰),但执行更新的不是主线程——它是工作线程之一。因此,我试图让主线程在知道它具有一致的快照后“传递”锁。

我们过去对整个集合使用单个锁,但随着它变得越来越大,小更新的争用和延迟高得令人无法接受。

解锁和重新锁定(在 ReentrantLock 上)是不安全的 - 另一个线程可能会在工作线程开始搜索之前修改段。

普通的信号量 可以处理不同线程的锁定和解锁。接下来出现的问题是谁应该释放信号量——工作线程需要一种方式来表示它已经获得了锁的所有权(因为它可能会在此时之前或之后抛出异常,并且主线程需要知道是否要清理向上。)单元测试也很棘手,因为您永远不知道信号量获取或释放是否发生在正确的线程中。

如果锁可以在其他方法中以可重入方式使用(它不会在线程之间传递),那将是一个奖励。

我想象需要 SemaphoreAtomicBooleanAtomicReference 的某种组合,但快速谷歌搜索没有显示任何示例.有什么理由不应该使用这种方法?

最佳答案

反向使用读/写锁可能会起作用。在这个习惯用法中,读锁持有者对数据结构执行并发写入(例如,数组中的独立槽)。写锁用于获取独占访问以执行一致的读取(例如,对数组求和)。这是一个很少使用的习语,但在那些古怪的情况下很优雅。您的问题有点难以理解,但这至少可以为具体解决方案提供一些灵感。我怀疑通过更深入的理解,可以简化问题,使经典解决方案更合适。

关于java - 可以从一个线程转移到另一个线程的锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4813440/

相关文章:

java - 尽管 AndroidManifest.xml 中提到了,为什么我的 Android 应用程序无法获得某些权限

java - RxJava 将新对象添加到流中

php - laravel 5.4 : pessimistic locking. 在事务完成之前避免选择一行

java - 使用 JFileChooser 选择文件

java - 停止 Eclipse/Gradle 生成 .project 和 .settings/

java - 在一组文档上使用 ForkJoinPool

haskell - `forkIO` 和 `putMVar` : what's going on under the hood?

c++ - 有条件地使用 std::lock_guard

c - 共享文件描述符上的共享锁

java - Nodejs 和 Java 之间的连接。当 java 客户端连接到 nodejs 服务器时,它显示错误,