Как сделать мьютекс в другом потоке? - PullRequest
0 голосов
/ 04 января 2019

Я хочу создать поток в цикле, и когда поток будет создан, не создавайте его снова, пока поток не будет завершен.Я использую код ниже, но он не работает, потому что мьютекс будет разблокирован, пока он уже разблокирован.Может кто-нибудь сказать мне, как это сделать?

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

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Похоже, что вы на самом деле хотите, чтобы в любой момент работал ровно один фоновый поток.Если это правда, я бы предложил полностью избавиться от блокировок, выбрав вместо этого 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() метод, как указано выше.Но если вам нужен более сложный шаблон связи, когда основной поток должен ждать в нескольких местах фонового потока, переменная условия более подходит.

0 голосов
/ 04 января 2019

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