32

我正在编写一个程序,其中有一个由多个线程共享的对象:

  • A)多个写线程写入对象(都运行相同的功能)
  • B) 每 5 秒访问一次对象的读取线程
  • C)访问对象的读取线程有用户请求

在写入对象时显然需要锁定对象,因为我们不希望多个线程同时写入对象。

我的问题是:

  1. 读取对象时是否也需要锁定对象?
  2. 我是否正确地认为,如果我们只是在编写时锁定对象,一个关键部分就足够了;但是如果我们在读或写的时候锁定对象,互斥量是必要的吗?

我问这个问题是因为在 Microsoft Office 中,两个 Word 实例无法以读/写访问模式访问文档;但是当文档以读/写模式打开时,可以打开另一个 Word 实例以只读模式访问文档。相同的逻辑是否适用于线程?

4

5 回答 5

23

正如 Ofir 已经写的那样——如果你尝试从其他线程正在修改的对象中读取数据——你可能会得到一些不一致状态的数据。

但是 - 如果您确定对象没有被修改,您当然可以从多个线程中读取它。一般来说,您所问的问题或多或少是读者-作家问题 - 请参阅http://en.wikipedia.org/wiki/Readers-writers_problem

最后 - 关键部分是一个抽象术语,可以使用互斥锁或监视器来实现。java 或 C#(同步、锁定)中关键部分的语法糖在幕后使用了监视器。

于 2010-01-31T12:52:43.393 回答
6

读取对象时是否也需要锁定对象?

如果其他东西可以同时写入它 - 是的。如果只能发生另一次读取 - 不。在你的情况下,我会说 - 是的。

我是否正确地认为,如果我们只是在编写时锁定对象,一个关键部分就足够了;但是如果我们在读或写的时候锁定对象,互斥量是必要的吗?

不,您可以对两者都使用关键部分,其他条件相同。互斥体在部分上添加了功能(例如,可以从多个进程中使用命名互斥体),但我认为您在这里不需要这些功能。

于 2010-01-31T12:46:12.003 回答
5

这是必要的,因为否则(除非操作是原子的)您可能正在读取中间状态。

您可能希望同时允许多个读取器,这需要(有点)更复杂的锁。

于 2010-01-31T12:44:13.253 回答
4
  1. 取决于您如何使用和阅读它。如果您的读取是原子的(即不会被写入中断)并且读取线程不依赖于写入线程,那么您也许可以跳过读取锁定。但是,如果您的“读取”操作需要一些时间并且需要大量的对象交互,那么您应该锁定它以供读取。

  2. 如果您的阅读不需要很长时间(即不会将写入线程延迟太久),那么临界区就足够了。

于 2010-01-31T12:47:17.570 回答
0

仅当两个进程可以更改相同的数据库表元素时才需要锁定。当您想读取数据时,它始终是安全的。您读取一致数据库的数据。更改数据的过程具有一致的影子版本,并且在您保存时将覆盖当前数据。但是,如果您正在运行取决于数据库元素的临界值的读取过程,您应该寻找表明这些值可能被更改的锁。所以你的阅读会被延迟,直到锁消失。

于 2014-08-01T22:06:47.340 回答