【问题标题】:Lock that can be transferred from one thread to another可以从一个线程转移到另一个线程的锁
【发布时间】:2011-01-27 06:35:36
【问题描述】:

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

这就是我想要它的原因:

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

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

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

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

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

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

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

【问题讨论】:

  • 并发最适合简单模型。鉴于您的描述的长度和模型的复杂性,我建议您尝试简化您的要求。恕我直言,它更有可能有效地工作。我知道唤醒特定线程的唯一方法是 Unsafe.park() 和 Unsafe.unpark(Thread) 但我不建议直接使用它们。
  • 如果你想要的只是一个可以传递的“锁”,为什么不使用令牌传递机制,将每个段锁作为一个令牌,并按字面意思传递呢?如果集合搜索时间足够长,这个令牌甚至可以是一个文件,文件充当锁。主线程可以简单地将“锁”给工作线程。
  • 是否可以通过具有关联“更新”的持久结构创建新结构而不是就地修改来以无锁方式建模?您的描述是一种解决方案,而不是您要解决的根本问题,因此很难提出建议。

标签: java concurrency locking atomic semaphore


【解决方案1】:

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

【讨论】:

  • 正如我所说,阅读ConcurrentHashMap的来源可能会更清楚。我的课程非常相似,只是当它执行与contains(Object) 等效的操作时,它会在(可能)不同的线程中搜索每个段。我会看看我是否可以调整问题以使其更清楚。我认为您的解决方案会起作用。
  • 我了解技术方面,但不了解行为方面。为什么要移动钥匙?为什么必须搜索(例如,为什么不使用 ConcurrentSkipListMap)?是什么契约使它与法线贴图不同?
  • 键没有单一的自然顺序。此搜索操作会进行“模糊”比较,并且必须检查段中的每个元素以寻找最接近的匹配项。修改一个键偶尔会改变它的 hashCode 使其属于不同的段。我必须自动移动它,以确保它在移动时不会被排除在搜索之外。
  • 好的 - 那么版本控制是解决这个问题的经典解决方案。这是使用持久数据结构或重放事务(放置/删除/移动)的副本(例如,更新提交到写入队列)来完成的。后者可以通过使用读取器/写入器锁来支持并发搜索,其中写入器锁是在有待重放的更新时获取的。要么允许搜索不阻塞其他写入者,而反向读/写锁将阻塞(但可以检查并让步以最小化这种情况)。
猜你喜欢
  • 1970-01-01
  • 2015-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多