简单数据类型的互斥量
Mutex for simple data types
我对并发还很陌生,我在决定如何使用互斥体时遇到了麻烦。目前,它们散布在我的两个线程交互的代码中。这样使用互斥锁合适吗?
class Foo
{
public:
void SetMember(int n) { AcquireMutex(..); n_ = n; ReleaseMutex(...);}
private:
Thread()
{
while(1)
{
AcquireMutex(..);
// Do something with n_
ReleaseMutex(...);
}
}
};
我有很多数据成员可以通过不同的线程从外部读取和设置,我发现跟踪所有互斥锁的获取和释放是一件令人头疼的事情。
不保证原始类型的变异是线程安全的,或者更具体地说是原子的。事实上,如果您查看 <atomic>
,您会注意到有几个专业,包括 std::atomic_int
.
Objects of atomic types are the only C++ objects that are free from data races; that is, if one thread writes to an atomic object while another thread reads from it, the behavior is well-defined.
为了具体回答您关于使用互斥锁的问题,是的,您在示例中使用互斥锁没有问题。通常,您希望尽可能短地持有互斥量。换句话说,如果你有一个做很多工作的函数,只锁定非线程安全代码周围的互斥锁,然后一旦代码是线程安全的就解锁它。
这种互斥的做法很幼稚,并不能避免死锁和其他并发问题。
您必须明确识别代码中两个进程同时访问会导致问题的位置,并在关键部分保护它们。并且你必须确保你不会让两个进程启动一个操作,因为另一个进程他们无法完成。
在其他地方,可能不需要保护,激活互斥量就太过分了。
很多时候,原子性不是单个变量所必需的,而是一组耦合变量所必需的。
我对并发还很陌生,我在决定如何使用互斥体时遇到了麻烦。目前,它们散布在我的两个线程交互的代码中。这样使用互斥锁合适吗?
class Foo
{
public:
void SetMember(int n) { AcquireMutex(..); n_ = n; ReleaseMutex(...);}
private:
Thread()
{
while(1)
{
AcquireMutex(..);
// Do something with n_
ReleaseMutex(...);
}
}
};
我有很多数据成员可以通过不同的线程从外部读取和设置,我发现跟踪所有互斥锁的获取和释放是一件令人头疼的事情。
不保证原始类型的变异是线程安全的,或者更具体地说是原子的。事实上,如果您查看 <atomic>
,您会注意到有几个专业,包括 std::atomic_int
.
Objects of atomic types are the only C++ objects that are free from data races; that is, if one thread writes to an atomic object while another thread reads from it, the behavior is well-defined.
为了具体回答您关于使用互斥锁的问题,是的,您在示例中使用互斥锁没有问题。通常,您希望尽可能短地持有互斥量。换句话说,如果你有一个做很多工作的函数,只锁定非线程安全代码周围的互斥锁,然后一旦代码是线程安全的就解锁它。
这种互斥的做法很幼稚,并不能避免死锁和其他并发问题。
您必须明确识别代码中两个进程同时访问会导致问题的位置,并在关键部分保护它们。并且你必须确保你不会让两个进程启动一个操作,因为另一个进程他们无法完成。
在其他地方,可能不需要保护,激活互斥量就太过分了。
很多时候,原子性不是单个变量所必需的,而是一组耦合变量所必需的。