【问题标题】:Use mutex or not in a concurrent reading在并发读取中使用或不使用互斥锁
【发布时间】:2016-11-17 09:50:28
【问题描述】:

我在 Linux 中使用 C++ 编程,并且正在使用 pthreads 库。我正在使用互斥锁来保护一些共享变量,但我不确定在这种特定情况下是否有必要使用互斥锁。

我有 3 个线程。共享变量是一个字符串(全局变量)。

Thread1 改变了它的值,然后 thread2 和 thread3 读取它的值并存储在另一个字符串中。

在这种情况下,字符串的值只被一个线程修改。两个线程并发读取时是否还需要使用互斥锁来保护共享变量?

【问题讨论】:

  • 只要有至少一个线程在修改对象,您就需要一个互斥锁。唯一不需要它的情况是每个人都在阅读。
  • 但是线程 2 和 3 只有在 Thread1 已经修改了它的值时才读取字符串的值。
  • 如果您可以确保线程 1 在其他任何人尝试读取字符串之前完成了对字符串的修改,那么您将处于每个人都读取的情况:不需要互斥锁。
  • 完美!非常感谢!
  • 在标准的范围内,是的,会有:至少有一次写入的不同步的同时访问被称为竞争条件,并触发未定义的行为。一些平台能够对某些简单数据类型执行无锁原子操作,但您不能再依赖该标准。为了解决这个问题,您可以使用std::atomic<bool>,它将转换为您平台的最佳操作,如果没有其他可用的,则降级为互斥体。

标签: c++ multithreading mutex


【解决方案1】:

“Thread1 改变了它的值,然后……”——如果“之后”意味着其他线程在改变之后创建,则不需要互斥锁;线程创建同步内存。如果它还有其他含义,那么您需要某种形式的同步,部分原因是不同线程中的“之后”没有同步就毫无意义。

【讨论】:

  • 正如你所说,(不同线程中的“之后”没有同步是没有意义的)同步是使用互斥锁进行的。因此,没有必要保护它们。谢谢!
  • @JulenUranga - 互斥锁不能保证在之后发生其他事情。它所做的只是确保它们不会同时发生(松散地说)。如果您需要让一个线程在另一个线程写入该值之后读取该值,则您需要某种方式来传达该值已被写入。
【解决方案2】:

您应该使用 shared_mutex(如果您不想使用 C++14/17,请从 boost 获取)(对于 C++14,您可以使用 shared_timed_mutex) .然后,如果要读取字符串,请执行 shared_lock,如果要在其上写入,请执行 unique_lock

如果两个共享锁相遇,它们不会发生冲突,也不会阻塞,但是共享锁和唯一锁会发生冲突,其中一个锁会阻塞,直到另一个锁完成。

【讨论】:

  • 我正在使用 pthreads 库,我不想更改它。尽管如此,还是感谢您的回答。
  • @JulenUranga 实际上,您是否使用 pthreads 是无关紧要的。锁不在乎!
  • 我知道!但我想保持结构并使用与线程相关的相同“功能”继续项目:)
  • @JulenUranga 我明白了。这根本不是一件坏事。但是,如果您找不到任何其他解决方案,请保留shared_mutex 解决方案作为最后的手段。此外,它是标准库的一部分,因此您不必为它添加额外的特殊库。干杯:)
【解决方案3】:

由于您使用的是 pthread,您可以使用 pthread_rwlock_t

为了更新对象,获得写锁是locked using pthread_rwlock_wrlock();只有在获得共享读锁with pthread_rwlock_rdlock() 后,所有读者才能访问该对象。由于写锁是独占的,而读锁是共享的,你会得到你想要的行为。

pthread_rwlock_t 读/写锁的使用示例可以在http://www.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.genprogc/using_readwrite_locks.htm 找到。

可以在https://docs.oracle.com/cd/E19455-01/806-5257/6je9h032u/index.html 上找到可用于pthread_rwlock_t 锁的调用的完整摘要。我已经复制了列出操作的表格:

Operation 

Initialize a read-write lock                   "pthread_rwlock_init(3THR)"

Read lock on read-write lock                   "pthread_rwlock_rdlock(3THR)"

Read lock with a nonblocking read-write lock   "pthread_rwlock_tryrdlock(3THR)"

Write lock on read-write lock                  "pthread_rwlock_wrlock(3THR)"

Write lock with a nonblocking read-write lock  "pthread_rwlock_trywrlock(3THR)"

Unlock a read-write lock                       "pthread_rwlock_unlock(3THR)"

Destroy a read-write lock                      "pthread_rwlock_destroy(3THR)" 

【讨论】:

    猜你喜欢
    • 2021-08-19
    • 2012-10-27
    • 1970-01-01
    • 2020-06-03
    • 2018-10-18
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多