C++ 这里需要读写锁吗

C++ 这里需要读写锁吗,c++,multithreading,thread-safety,mutex,C++,Multithreading,Thread Safety,Mutex,我正在编写一个多线程代码。我不确定是否需要读写锁定机制。请你检查一下用例,告诉我我必须使用读写锁还是普通互斥锁就可以了 用例: 1) 具有两个变量的类。在执行操作之前,每个线程都会访问它们。 2) 当出现错误时,这些变量会更新以反映错误场景。 因此,读取这些变量的线程可以做出不同的决定(包括中止) 这里,在第二点中,我需要更新数据。在第一点中,每个线程都将使用这些数据。所以,我的问题是更新数据时是否必须使用写锁,读取数据时是否必须使用读锁。(注意:两个变量都在内存中。只有一个布尔标志和字符串)

我正在编写一个多线程代码。我不确定是否需要读写锁定机制。请你检查一下用例,告诉我我必须使用读写锁还是普通互斥锁就可以了

用例: 1) 具有两个变量的类。在执行操作之前,每个线程都会访问它们。 2) 当出现错误时,这些变量会更新以反映错误场景。 因此,读取这些变量的线程可以做出不同的决定(包括中止)

这里,在第二点中,我需要更新数据。在第一点中,每个线程都将使用这些数据。所以,我的问题是更新数据时是否必须使用写锁,读取数据时是否必须使用读锁。(注意:两个变量都在内存中。只有一个布尔标志和字符串)

我很困惑,因为我的两个变量都在记忆中。因此,操作系统在维护完整性时也要小心。我的意思是,当某个线程在互斥体中写入数据时,可以有1到2个线程缺少更新的值

请告诉我是对还是错?另外,请告诉我是否必须使用读写锁,或者只使用普通互斥锁即可

更新:很抱歉,我没有给出平台和编译器的名称。我使用RHEL5.0,使用GCC4.6。我的平台是x86_64。但我不希望我的代码是特定于操作系统的,因为我们将很快将代码移植到Solaris 10

因此,读取这些变量的线程可以做出不同的决定(包括中止)

因此,每个线程都需要确保读取更新的数据。此外,由于变量是共享的,因此还需要注意竞争条件

因此,简而言之,在读取和写入这些共享变量时,需要使用读/写锁

查看是否可以使用易失性变量-这应该可以避免在读取值时使用锁(但是写入仍应使用锁)。这只适用于你所说的-

我的意思是,当某个线程在互斥体中写入数据时,我可以忍受1个或2个线程缺少更新的值

因此,读取这些变量的线程可以做出不同的决定(包括中止)

因此,每个线程都需要确保读取更新的数据。此外,由于变量是共享的,因此还需要注意竞争条件

因此,简而言之,在读取和写入这些共享变量时,需要使用读/写锁

查看是否可以使用易失性变量-这应该可以避免在读取值时使用锁(但是写入仍应使用锁)。这只适用于你所说的-

我的意思是,当某个线程在互斥体中写入数据时,我可以忍受1个或2个线程缺少更新的值


如果它们是原子变量(C1x
stdatomic.h
或C++0x
atomic
),则不需要读/写锁。在早期的C/C++标准中,根本没有使用多线程的可移植方式,因此您需要研究正在使用的实现是如何工作的。在大多数实现中,可以用一条机器指令访问的数据类型是原子的


请注意,仅仅拥有一个原子变量是不够的——您可能还需要将其声明为volatile,以确保编译器不会执行会导致您错过其他线程更新的操作。

如果它们是原子变量(C1x
stdatomic.h
或C++0x
原子变量),那么就不需要读/写锁了。在早期的C/C++标准中,根本没有使用多线程的可移植方式,因此您需要研究正在使用的实现是如何工作的。在大多数实现中,可以用一条机器指令访问的数据类型是原子的


请注意,仅仅拥有一个原子变量是不够的——您可能还需要将其声明为volatile,以确保编译器不会执行会导致您错过其他线程更新的操作。

首先,忽略那些谈论volatile的其他回答者,而它给人的任何虚假的安全感都是——虚假的

现在,是否需要锁取决于您对这些变量所做的操作。您至少需要一个内存屏障(锁意味着一个)

让我们举个例子:

  • 一个标志是错误标志。如果为零,则继续,否则中止
  • 另一个标志是诊断代码标志。它给出了错误的确切原因
在这种情况下,一种选择是执行以下操作:

  • 读取错误标志时不带锁,但在读取后带有读取内存障碍
  • 发生错误时,锁定,设置诊断代码和错误标志,然后释放锁。如果已设置诊断代码,请立即释放锁
需要内存屏障,否则编译器(或CPU!)可能会选择为每次读取缓存相同的结果

当然,如果两个变量的语义不同,答案可能会有所不同。你需要更具体一些

请注意,指定锁和内存屏障的确切机制取决于编译器。C++0x提供了一种可移植的机制,但是很少有编译器完全实现C++0x标准。请指定编译器和操作系统以获得更详细的答案


至于您的输出数据,您几乎肯定需要一个锁。不过,尽量避免过多地使用这些锁,因为过多的锁争用会降低您的性能。

首先,忽略那些谈论volatile的回答者,而它给人的任何虚假的安全感都是——虚假的

现在,是否需要锁取决于您对这些变量所做的操作。您至少需要一个内存屏障(锁意味着一个)

让我们举个例子:

  • 一个标志是错误标志。如果为零,则继续,否则为