Mutex 没有像我预期的那样工作。我的错误是什么?
Mutex does not work as I expect. What is my mistake?
我试图找出数据竞赛的主题,并编写了这段代码。这里我们使用共享元素 wnd
。我认为通过在 while 循环中放置锁,我会禁止 th1
线程与 wnd
一起工作,但这并没有发生,我看到 th1
线程的输出畅通无阻。
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
int main()
{
bool wnd = true;
std::mutex mutex;
std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
std::thread th1([&]() {
int i = 0;
while (true)
{
++i;
if (wnd)
std::cout << i << " WND TRUE" << std::endl;
else
std::cout << i << " WND FALSE" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
while (true)
{
lock.lock();
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
if (wnd)
wnd = false;
else
wnd = true;
lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
th1.join();
return 0;
}
说实话,我希望看到 th1
线程在主线程在锁定部分内时停止打印 2+ 秒。
您没有正确使用互斥锁,特别是 std::unique_lock
。
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
int main()
{
bool wnd = true;
std::mutex mutex;
std::thread th1{[&]() {
for (int i = 0; i<10000; ++i)
{ std::unique_lock<std::mutex> lock(mutex);
std::cout << i << "\tWND\t " << std::boolalpha << wnd << std::endl;
};
}};
for (int i = 0; i<30; ++i)
{ std::unique_lock<std::mutex> lock(mutex);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
wnd = !wnd;
};
th1.join();
}
std::unique_lock
uses its constructor operand as a resource whose acquisition is lock
and release is unlock
. It is designed to use RAII
作为保证互斥量正确 lock/unlock 序列的一种方式。延迟锁定仅意味着互斥锁在 std::unique_lock
的生命周期开始时未被锁定,这不是通常的用例。您可以手动 lock/unlock 互斥体,但这通常会导致可维护性降低,代码量增加 error-prone。
请记住,如果所涉及的线程没有争夺互斥体的所有权,则两者都不会等待对方;在您的原始程序中,工作线程没有接触互斥锁。但是在上面的程序中,两个线程都在竞争锁定互斥量;获胜者有机会继续他想做的事,而失败者必须等到互斥体解锁 - 这样他才能获得它的所有权。
我试图找出数据竞赛的主题,并编写了这段代码。这里我们使用共享元素 wnd
。我认为通过在 while 循环中放置锁,我会禁止 th1
线程与 wnd
一起工作,但这并没有发生,我看到 th1
线程的输出畅通无阻。
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
int main()
{
bool wnd = true;
std::mutex mutex;
std::unique_lock<std::mutex> lock(mutex, std::defer_lock);
std::thread th1([&]() {
int i = 0;
while (true)
{
++i;
if (wnd)
std::cout << i << " WND TRUE" << std::endl;
else
std::cout << i << " WND FALSE" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
while (true)
{
lock.lock();
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
if (wnd)
wnd = false;
else
wnd = true;
lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
th1.join();
return 0;
}
说实话,我希望看到 th1
线程在主线程在锁定部分内时停止打印 2+ 秒。
您没有正确使用互斥锁,特别是 std::unique_lock
。
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
int main()
{
bool wnd = true;
std::mutex mutex;
std::thread th1{[&]() {
for (int i = 0; i<10000; ++i)
{ std::unique_lock<std::mutex> lock(mutex);
std::cout << i << "\tWND\t " << std::boolalpha << wnd << std::endl;
};
}};
for (int i = 0; i<30; ++i)
{ std::unique_lock<std::mutex> lock(mutex);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
wnd = !wnd;
};
th1.join();
}
std::unique_lock
uses its constructor operand as a resource whose acquisition is lock
and release is unlock
. It is designed to use RAII
作为保证互斥量正确 lock/unlock 序列的一种方式。延迟锁定仅意味着互斥锁在 std::unique_lock
的生命周期开始时未被锁定,这不是通常的用例。您可以手动 lock/unlock 互斥体,但这通常会导致可维护性降低,代码量增加 error-prone。
请记住,如果所涉及的线程没有争夺互斥体的所有权,则两者都不会等待对方;在您的原始程序中,工作线程没有接触互斥锁。但是在上面的程序中,两个线程都在竞争锁定互斥量;获胜者有机会继续他想做的事,而失败者必须等到互斥体解锁 - 这样他才能获得它的所有权。