一个互斥锁与多个互斥锁.哪一个更适合线程池?
One mutex vs Multiple mutexes. Which one is better for the thread pool?
这里的例子,只是想保护iData
以确保只有一个线程同时访问它。
struct myData;
myData iData;
方法一,调用函数内部互斥锁(可以创建多个互斥锁):
void _proceedTest(myData &data)
{
std::mutex mtx;
std::unique_lock<std::mutex> lk(mtx);
modifyData(data);
lk.unlock;
}
int const nMaxThreads = std::thread::hardware_concurrency();
vector<std::thread> threads;
for (int iThread = 0; iThread < nMaxThreads; ++iThread)
{
threads.push_back(std::thread(_proceedTest, iData));
}
for (auto& th : threads) th.join();
方法2,只使用一个互斥锁:
void _proceedTest(myData &data, std::mutex &mtx)
{
std::unique_lock<std::mutex> lk(mtx);
modifyData(data);
lk.unlock;
}
std::mutex mtx;
int const nMaxThreads = std::thread::hardware_concurrency();
vector<std::thread> threads;
for (int iThread = 0; iThread < nMaxThreads; ++iThread)
{
threads.push_back(std::thread(_proceedTest, iData, mtx));
}
for (auto& th : threads) th.join();
- 我想确保方法 1(多个互斥锁)确保只有一个线程可以同时访问 iData。 如果方法 1
- 正确,不确定方法 1 是否比方法 2 更好? 谢谢!
- 确保方法 1(多个互斥锁)确保只有一个线程可以同时访问 iData。
您的第一个示例在堆栈上创建一个局部互斥变量,它不会与其他线程共享。因此,它完全没用。
它不会保证独占访问iData
。
如果方法 1
- 正确,不确定方法 1 比方法 2 更好?
这是不正确的。
其他答案在技术层面上是正确的,但缺少一个重要的语言独立的东西:你总是喜欢尽量减少不同互斥锁/锁/...!
因为:一旦线程需要获取多个东西才能做某事(然后释放所有获取的锁),顺序就变得至关重要。
当你有两个锁,并且你必须有不同的代码段,比如:
getLockA() {
getLockB() {
do something
release B
release A
和
getLockB() {
getLockA() {
您可能会很快遇到死锁 - 因为两个线程/进程可以各自获取一个锁 - 然后它们都被卡住,等待另一个线程释放其锁。当然 - 当查看上面的例子时,"你永远不会犯错误,总是先走 A 然后 B"。但是,如果这些锁存在于应用程序的完全不同的部分怎么办?它们不是在相同的方法或类中获取的,而是在 3、5 次嵌套方法调用的过程中获得的?
因此:当您可以使用一把锁解决您的问题时 - 仅使用一把锁!完成某事所需的锁越多,最终陷入死锁的风险就越高。
方法 1 仅在将互斥变量设为static
时才有效。
void _proceedTest(myData &data)
{
static std::mutex mtx;
std::unique_lock<std::mutex> lk(mtx);
modifyData(data);
lk.unlock;
}
这将使mtx
由所有进入_proceedTest
的线程共享。
由于static
函数范围变量仅对函数的用户可见,因此对于传入的data
来说,它实际上并不是一个足够的锁。这是因为可以想象,多个线程可以调用每个线程想要操作的不同函数data
。
因此,即使方法 1 是可以挽救的,方法 2 仍然更好,即使锁和数据之间的内聚力很弱。
一旦您离开_proceedTest范围,版本 1 中的互斥锁将超出范围,像这样锁定互斥锁是没有意义的,因为它永远不会被其他线程访问。
在第二个版本中,多个线程可以共享互斥锁(只要它不超出范围,例如作为类成员),这样一个线程可以锁定它,另一个线程可以看到它被锁定(并且也无法锁定它,因此称为互斥)。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 当我在其中一个线程执行中(在activemq-cpp中)捕获到特定值时,我如何终止/停止所有其他线程
- 试图创建一个多线程程序来查找0-100000000之间的总素数
- 为什么一个向量上的多线程操作很慢
- 在另一个线程中调用luaL_error会引发qWarning
- 全局变量 多读取器 一个写入器多线程安全?
- C++一个线程如何正确通信其任务已完成?
- 最佳做法是从另一个线程访问 qml 中的Q_PROPERTY
- C++线程:如何在一个线程仍在运行时阻止另一个线程执行 (Win32)
- 是否可以创建一个从不同类调用函数的线程?
- 如何制作一个只能在一个线程上同时执行的函数?
- 结束另一个线程中使用的对象的生存期
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 一个线程等待多个线程事件
- 两个线程一个使用流 Api,另一个线程创建文件失败并出现错误ERROR_SHARING_VIOLATION
- C 两个线程一个用于输入,一个用于输出
- 2个线程 - 一个带有OpenGL窗口的线程,第二个带有WXWIDGETS的窗口
- 每个线程一个类实例,C++11
- 多线程-一个作家和一个读者-我们需要使用储物柜吗
- Cuda如何从全局函数运行多个线程?一个运行多个线程的内核