【问题标题】:pthreads: a thread that triggers other threadspthreads:触发其他线程的线程
【发布时间】:2012-10-12 17:47:01
【问题描述】:

你好, 我是多线程编程的新手。 我正在尝试创建一个创建线程 THREAD1 的代码,在它完成某些操作后,它会触发另外两个线程,例如 THREAD2 和 THREAD3,然后退出。

我写了两个可能的解决方案。

1) 使用条件变量(不工作:在某些情况下我会遇到死锁):

pthread_mutex_t ready_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  ready_cond  = PTHREAD_COND_INITIALIZER;
bool ready = false;

void* trigger(void*);
void* func1(void*);
void* func2(void*);

int main()
{
    pthread_t thread1;
    pthread_t thread2;
    pthread_t thread3;  
    pthread_create(&thread1, 0, &trigger, 0);
    pthread_create(&thread2, 0, &func1, 0);
    pthread_create(&thread3, 0, &func2, 0);
    pthread_join(thread1, 0);
    pthread_join(thread2, 0);
    pthread_join(thread3, 0);
}

void *trigger(void*)
{
    pthread_mutex_lock(&ready_mutex);
    ready = true;
    pthread_cond_broadcast(&ready_cond);
    pthread_mutex_unlock(&ready_mutex);
    return 0;
}

void *func1(void*)
{
    while (!ready) // Needed to avoid spuriuos wake-up
    {
        pthread_mutex_lock(&ready_mutex);
        pthread_cond_wait(&ready_cond, &ready_mutex);
        pthread_mutex_unlock(&ready_mutex);
    }
    std::cout << "In 'func1'>> Do something" << std::endl;
    return 0;
}

void *func2(void*)
{
    while (!ready) // Needed to avoid spuriuos wake-up
    {
        pthread_mutex_lock(&ready_mutex);
        pthread_cond_wait(&ready_cond, &ready_mutex);
        pthread_mutex_unlock(&ready_mutex);
    }
    std::cout << "In 'func2'>> Do something" << std::endl;
    return 0;
}

2) THREAD1 直接创建另外两个线程。

pthread_mutex_t ready_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  ready_cond  = PTHREAD_COND_INITIALIZER;

pthread_t thread1;
pthread_t thread2;
pthread_t thread3;

void* trigger(void*);
void* func1(void*);
void* func2(void*);

int main()
{
    pthread_create(&thread1, 0, &trigger, 0);

    pthread_join(thread1, 0);
    pthread_join(thread2, 0);
    pthread_join(thread3, 0);
}

void *trigger(void*)
{
    std::cout << "In 'trigger'>> Do something" << std::endl;

    pthread_create(&thread2, 0, &func1, 0);
    pthread_create(&thread3, 0, &func2, 0);

    return 0;
}

void *func1(void*)
{
    std::cout << "In 'func1'>> Do something" << std::endl;

    return 0;
}

void *func2(void*)
{
    std::cout << "In 'func2'>> Do something" << std::endl;

    return 0;
}

我想知道你的意见。 非常感谢

【问题讨论】:

  • 您的第二个实现似乎运行良好,您认为它有什么问题?
  • 您的第二个选项更干净、更美观。我会这样做的。
  • @CaptainMurphy:我只是想知道是否有更好的方法来实现这个目标。从 POSIX 手册页来看,在我看来,条件变量更适合此目标,因为它们可用于发出特定事件的信号。
  • 你的“虚假唤醒”循环不太正确:你想lock,然后是while (!read) cond_wait(),然后是unlock。因为它是您在没有首先锁定互斥锁的情况下检查受互斥锁保护的变量 (ready) 的值 - 不好。
  • @pilcrow:是的,我知道。 Maxim Yegorushkin 已经指出了这一点(见下面的第一个答案)。谢谢。

标签: c++ multithreading synchronization pthreads


【解决方案1】:

使用条件变量(不起作用:在某些情况下我遇到了死锁):

检查共享变量ready 的状态时,代码不会锁定互斥锁。当它确实锁定了互斥锁时,ready 可能已经发生了很大的变化,这就是你看到死锁的原因。

使用条件变量等待状态更改的正确版本是(省略错误检查):

pthread_mutex_lock(&ready_mutex);
while(!ready) // Needed to avoid spuriuos wake-up
    pthread_cond_wait(&ready_cond, &ready_mutex);
// ready == true here
pthread_mutex_unlock(&ready_mutex);

以上假设 ready 只有在持有相同的互斥锁时才会更改。

【讨论】:

  • 是的,你是对的。那么,回到我的问题,我应该使用条件变量(解决方案#1)还是延迟线程创建(解决方案#2)?
  • @seg.fault 我会使用Occam's razor:给定一个问题的多种解决方案,选择更简单的一个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-28
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多