何时或为什么应该在 RwLock 上使用 Mutex?

84

当我阅读MutexRwLock的文档时,我看到的区别如下:

  • Mutex一次只能有一个读者或写者。
  • RwLock一次可以有一个写者或多个读者。

按照这种方式,RwLock似乎总是比Mutex更好(更少受限),那么我为什么还要使用它呢?

2个回答

76
有时在Rust中,使用MutexRwLock更好:

RwLock<T>需要更多的边界来使T线程安全:

换句话说,Mutex是唯一一个可以使T同步的包装器。我在Reddit上找到了一个好的、直观的解释:

由于这些限制,RwLock要求其内容是同步的,即两个线程同时拥有该类型的 &ptr 是安全的。Mutex仅要求数据是可发送的,因为你可以从概念上将其视为当你锁定Mutex时,它会将数据发送到您的线程,当您解锁它时,数据会发送到另一个线程。

当你的T只是Send而不是Sync时,请使用Mutex

防止写入者饥饿

RwLock没有特定的实现,因为它使用系统的实现。一些读写锁可能会受到writer starvation的影响,而Mutex则不会出现这种问题。

当你可能有太多的读取器以至于无法让写入器获得锁时,应该使用Mutex


4
一个天真的读写锁实现会让写者饿死。如果我负责的应用需要使用读写锁,而且必须在某些平台上部署“标准”读写锁很差的情况下,我会编写一个适合我的应用需求的自己的读写锁,而不是采用简单的互斥体。 - Solomon Slow
5
我会涉及到“性能”和“意图”。也就是说,(1)读写锁实现通常更复杂,因此速度较慢;(2)如果您的算法只需要互斥锁,使用读写锁只会使读者感到困惑而没有任何好处。甚至可能会增加正确性问题:如果您通过随机将互斥锁升级为读写锁来避开锁定问题,那么您就会遇到麻烦。多线程和分布式编程需要清晰的数据流模型;随意添加锁并不能神奇地修正数据流。 - Matthieu M.
13
尽管这个问题在“rust”标签下,但我发现Java中ReadWriteLock接口的文档对于用户在选择互斥锁和读写锁之间时需要考虑的各种因素以及可能的实现权衡进行了非常全面的讨论。 - Dmitry Timofeev
1
@DmitryTimofeev 谢谢你的链接!我一定要花时间来完善这个答案。 - Boiethios

9

Mutex是一种简单的锁定方法,用于控制对共享资源的访问。

  • 同时,只有一个线程可以控制一个Mutex,被锁定的线程可以访问共享资源。
  • 如果另一个线程想要锁定已经被mutex锁定的资源,则该线程将挂起,直到被锁定的线程释放mutex。

读写锁比互斥锁更加复杂。

  • 使用mutex的线程缺乏读并发性。
  • 当存在更多的读操作和较少的写操作时,可以使用读写锁来提高线程的读并发性。

让我为自己总结一下:

  • 读写锁的实现比互斥锁更加复杂,性能也较差。
  • 读写锁支持多个线程同时读取,而mutex锁不支持多个线程同时读取,因此读写锁具有较高的并发性。

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