如何在另一个线程中创建互斥锁?
How to make a mutex in another thread?
我想在循环中创建一个线程,创建线程后,在线程完成之前不要再次创建它。我使用了下面的代码,但它不起作用,因为互斥锁会在它已经解锁时解锁。谁能告诉我怎么做?
#include <iostream>
#include <thread>
#include <mutex>
int counter = 0;
std::mutex mtx;
std::thread t;
void test_mutex_t2()
{
std::lock_guard<std::mutex> lock(mtx);
counter++;
}
void test_mutex_t1()
{
while (1) {
if (mtx.try_lock())
{
t = std::thread(test_mutex_t2);
mtx.unlock();
}
}
}
int main()
{
test_mutex_t1();
return 0;
}
std::thread
必须 detach
或 join
:
std::mutex mtx;
std::thread t;
void test_mutex_t2()
{
std::lock_guard<std::mutex> lock(mtx);
counter++;
}
void test_mutex_t1()
{
while (1) {
if (mtx.try_lock())
{
t = std::thread(test_mutex_t2);
t.detach();
mtx.unlock();
}
}
}
听起来您真正想要的是在任何时候都只有一个后台线程 运行。如果那是真的,我会建议完全摆脱锁,而是在退出循环之前选择 join()
线程。像这样:
while (true) {
auto thr = std::thread(test_mutex_t2);
thr.join(); // Will block until thread exits
}
不过,我还想指出,这意味着您将 正好 一个线程 运行。这就提出了一个问题,你为什么要使用线程?您正在产生额外的线程只是为了进行同步工作。
如果你真的想要多线程,你需要一个不同的同步原语。从根本上说,互斥量旨在保护对单个资源的访问。你要做的是从后台线程communicate到主线程,当后台线程做了一些事情(完成,在本例中)时通知主线程。这通常通过条件变量或信号量来完成。 std::condition_variable
class 实现了其中的第一个。
我建议向线程函数传递一个条件变量,用于在主线程完成时提醒它。像这样:
void thread_func(std::condition_variable* cv) {
// do work
cv->notify_one();
}
int main(void) {
std::condition_variable cv;
std::mutex lock;
while (true) {
std::unique_lock<std::mutex> lock(mut);
auto thr = std::thread(thread_func, &cv);
cv.wait(lock); // Wait for background thread to notify us
thr.join();
}
}
同样,对于这个简单的例子来说,这太过分了;我会像上面那样使用 join()
方法。但是如果你想有一个更复杂的通信模式,主线程需要在多个地方等待后台线程,条件变量更合适。
我想在循环中创建一个线程,创建线程后,在线程完成之前不要再次创建它。我使用了下面的代码,但它不起作用,因为互斥锁会在它已经解锁时解锁。谁能告诉我怎么做?
#include <iostream>
#include <thread>
#include <mutex>
int counter = 0;
std::mutex mtx;
std::thread t;
void test_mutex_t2()
{
std::lock_guard<std::mutex> lock(mtx);
counter++;
}
void test_mutex_t1()
{
while (1) {
if (mtx.try_lock())
{
t = std::thread(test_mutex_t2);
mtx.unlock();
}
}
}
int main()
{
test_mutex_t1();
return 0;
}
std::thread
必须 detach
或 join
:
std::mutex mtx;
std::thread t;
void test_mutex_t2()
{
std::lock_guard<std::mutex> lock(mtx);
counter++;
}
void test_mutex_t1()
{
while (1) {
if (mtx.try_lock())
{
t = std::thread(test_mutex_t2);
t.detach();
mtx.unlock();
}
}
}
听起来您真正想要的是在任何时候都只有一个后台线程 运行。如果那是真的,我会建议完全摆脱锁,而是在退出循环之前选择 join()
线程。像这样:
while (true) {
auto thr = std::thread(test_mutex_t2);
thr.join(); // Will block until thread exits
}
不过,我还想指出,这意味着您将 正好 一个线程 运行。这就提出了一个问题,你为什么要使用线程?您正在产生额外的线程只是为了进行同步工作。
如果你真的想要多线程,你需要一个不同的同步原语。从根本上说,互斥量旨在保护对单个资源的访问。你要做的是从后台线程communicate到主线程,当后台线程做了一些事情(完成,在本例中)时通知主线程。这通常通过条件变量或信号量来完成。 std::condition_variable
class 实现了其中的第一个。
我建议向线程函数传递一个条件变量,用于在主线程完成时提醒它。像这样:
void thread_func(std::condition_variable* cv) {
// do work
cv->notify_one();
}
int main(void) {
std::condition_variable cv;
std::mutex lock;
while (true) {
std::unique_lock<std::mutex> lock(mut);
auto thr = std::thread(thread_func, &cv);
cv.wait(lock); // Wait for background thread to notify us
thr.join();
}
}
同样,对于这个简单的例子来说,这太过分了;我会像上面那样使用 join()
方法。但是如果你想有一个更复杂的通信模式,主线程需要在多个地方等待后台线程,条件变量更合适。