【问题标题】:How to make a mutex in another thread?如何在另一个线程中创建互斥锁?
【发布时间】:2019-01-04 03:11:48
【问题描述】:

我想在一个循环中创建一个线程,并且在创建线程时,在线程完成之前不要再次创建它。我使用下面的代码,但它不起作用,因为互斥锁将在它已经解锁时解锁。谁能告诉我怎么做?

#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;
}

【问题讨论】:

  • 你为什么用try_lock()而不是lock()
  • 什么意思,"互斥锁在它已经解锁的时候会解锁"
  • 听起来你只想要一个线程运行,对吗?如果是这样,创建线程然后在循环结束时调用其join 方法的循环似乎更简单。
  • 我只想创建一个线程来做大量的事情,比如图像识别,但是主循环不能被阻塞,当一个线程创建时,主循环不能创建另一个线程。感谢您的通知。
  • 你可以保持你的线程运行,只要它完成它的工作就交给它一批新的数据? (查找“生产者消费者”)

标签: c++ multithreading mutex


【解决方案1】:

std::thread必须detachjoin:

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();
        }
    }
}

【讨论】:

  • 谢谢回答。但是我不想在线程运行时阻塞循环!
  • 在这种情况下,使用两个互斥锁怎么样?我已经相应地编辑了代码
  • @emcute0319 “不想阻塞循环”是什么意思?循环所做的只是创建一个线程,你为什么要关心它是否被阻塞?它在做其他工作吗?
  • 是的,这只是一个小测试。我对C++不熟悉。所以我做测试。
  • 这不是解决方案。有一个竞争条件。主线程可能解锁互斥体,try_lock调用可能成功,在后台线程获取互斥体之前可能会创建另一个线程。
【解决方案2】:

听起来您真正想要的是随时运行一个后台线程。如果这是真的,我建议完全摆脱锁,在退出循环之前选择join() 线程。像这样的:

while (true) {
    auto thr = std::thread(test_mutex_t2);
    thr.join(); // Will block until thread exits
}

不过,我还想指出,这意味着您将恰好运行一个线程。这就提出了一个问题,你为什么要使用线程?你产生额外的线程只是为了做同步工作。

如果您确实需要多个线程,则需要不同的同步原语。从根本上说,互斥锁旨在保护对单个资源的访问。您要做的是从后台线程通信到主线程,当后台线程完成某事(在本例中为完成)时通知主线程。这通常通过条件变量或信号量来完成。 std::condition_variable 类实现了其中的第一个。

我建议给线程函数传递一个条件变量,当主线程完成时它会用它来提醒主线程。像这样的:

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() 方法。但是如果你想要一个更复杂的通信模式,主线程需要在多个地方等待后台线程,条件变量更合适。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-21
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多