【问题标题】:pthread_cond_wait wake many threads examplepthread_cond_wait 唤醒多线程示例
【发布时间】:2023-12-06 07:56:01
【问题描述】:

pthread_cond_wait 唤醒多线程示例

在线程 0 的某些广播中唤醒线程 1 和 3 的代码。

设置:Win7 和 mingw32,g++ 4.8.1 和 mingw32-pthreads-w32 pthread条件变量

解决方案: http://pastebin.com/X8aQ5Fz8

#include <iostream>
#include <string>
#include <list>
#include <map>
#include <pthread.h>
#include <fstream>

#include <sstream> // for ostringstream

#define N_THREAD 7

using namespace std;

// Prototypes
int main();
int scheduler();
void *worker_thread(void *ptr);
string atomic_output(int my_int, int thread_id);

// Global variables
//pthread_t thread0, thread1, thread2, thread3, thread4, thread5, thread6, thread7;

pthread_t m_thread[N_THREAD];
int count = 1;
pthread_mutex_t count_mutex     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  condition_var   = PTHREAD_COND_INITIALIZER;


// Main
int main() {

    cout << "Launching main. \n";

    //Start to monitor for exceptions
    register_exception_handler();

    //Start scheduler
    scheduler();

    return 0;
}


// Scheduler
int scheduler() {
    // Starting scheduler log file
    ofstream scheduler_log;
    scheduler_log.open ("scheduler_log.txt");
    //scheduler_log << "[Scheduler] Starting." << endl;
    cout << "[Scheduler] Starting.  \n";

    // Scheduler::Main Section

    int thread_id[N_THREAD];

    for(int i=0;i<N_THREAD;i++) {
        thread_id[i] = i;
        pthread_create( &m_thread[i], NULL, worker_thread, (void *) &thread_id[i]);
    }

    for(int i=0;i<N_THREAD;i++)
        pthread_join(m_thread[i], NULL);


    cout << "[Scheduler] Ending. \n";
    // Closing scheduler log file
    scheduler_log.close();

    return 0;
}

string atomic_output(int my_int, int thread_id) {
    ostringstream stm;
    stm << "Thread ";
    stm << thread_id;
    stm << ": ";


    //count fn
    stm << my_int;
    stm << "\n";


    //stm << "Finished. \n";

    return stm.str();
}

void *worker_thread(void *ptr) {
    string line;
    //int boo = 0;

    int thread_id = *(int *) ptr;

    //if(thread_id == 0)
    //  pthread_mutex_lock( &count_mutex );

    for(int i=0;i<10;i++) {
        //boo++;

        if (thread_id == 1) {

            pthread_mutex_lock(&count_mutex);
            while (count == 1) {
                cout << "[Thread 1] Before pthread_cond_wait...\n";
                pthread_cond_wait( &condition_var, &count_mutex );
                cout << "[Thread 1] After pthread_cond_wait...\n";
            }
            pthread_mutex_unlock(&count_mutex);

        }

        if (thread_id == 3) {

            pthread_mutex_lock(&count_mutex);
            while (count == 1) {
                cout << "[Thread 3] Before pthread_cond_wait...\n";
                pthread_cond_wait( &condition_var, &count_mutex );
                cout << "[Thread 3] After pthread_cond_wait...\n";
            }
            pthread_mutex_unlock(&count_mutex);
        }

        //count fn
        line = atomic_output(i, *(int *)ptr);
        cout << line;   

        if (i == 5) {
            if(thread_id == 0) {
                pthread_mutex_lock( &count_mutex );
                count = 0;
                pthread_mutex_unlock( &count_mutex );
                pthread_cond_broadcast(&condition_var);
            }
        }



    }

    //line = atomic_output(0, *(int *)ptr);
    //cout << line;
}

(旧)-= 我试过的 =-

*编辑:代码中的早期问题是使用 while(0) 而不是 while(predicate)。将其保留在那里以便于 cmets 参考。

代码 1:http://pastebin.com/rCbYjPKi

我试图 while(0) pthread_cond_wait( &condition_var, &count_mutex ); 与 pthread_cond_broadcast(&condition_var); ...线程不尊重条件。

条件证明不尊重:http://pastebin.com/GW1cg4fY

Thread 0: 0
Thread 0: 1
Thread 0: 2
Thread 0: 3
Thread 2: 0
Thread 6: 0
Thread 1: 0 <-- Here, Thread 1 is not supposed to tick before Thread 0 hit 5. Thread 0 is at 3.

代码2:http://pastebin.com/g3E0Mw9W

我试过 pthread_cond_wait( &condition_var, &count_mutex );在线程 1 和 3 中,程序没有返回。

线程 1 或线程 3 永远等待。即使使用广播说它应该唤醒所有等待的线程。显然有些东西不工作,代码或库?

更多:

我尝试先解锁互斥锁,然后再进行广播。我试过广播然后解锁。两者都不起作用。

我尝试使用信号而不是广播,同样的问题。

我无法使用的参考文献(*谷歌搜索)

http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

http://docs.oracle.com/cd/E19455-01/806-5257/6je9h032r/index.html

http://www-01.ibm.com/support/knowledgecenter/ssw_i5_54/apis/users_76.htm

代码 3:http://pastebin.com/tKP7F8a8

尝试使用谓词变量计数来修复竞争问题条件。还是个问题,不阻止thread1和thread3在thread0在0到5之间运行。

从线程 0 调用某些函数时唤醒线程 1 和 3 的代码是什么

【问题讨论】:

  • 我们能看到代码吗?漂亮吗?
  • 直接在问题中添加代码:)
  • 你能搜索一下如何使用条件变量的例子吗?或者询问如何使用它们并省略一大堆与您的问题真正无关的代码。
  • 我做到了,它们都不能用于超过 2 个线程。在问题末尾添加了参考...
  • 有几个突出的问题。第一个是您假设pthread_t 是一个整数类型。第二个是竞争条件,因为您假设线程“0”将是第一个运行的线程,因此首先成功锁定了count_mutex。为什么,如果你已经有了“整数”thread_id,你在调用atomic_output 时使用ptr(这个名字很奇怪,因为它没有输出)。

标签: c++ pthreads mingw mutex mingw32


【解决方案1】:
if(thread_id == 0)
    pthread_mutex_lock( &count_mutex );

for(int i=0;i<10;i++) {
    //boo++;

    if (thread_id == 1) {
        while(0)
            pthread_cond_wait( &condition_var, &count_mutex );
    }

这些都没有任何意义。等待条件变量的正确方法是:

pthread_mutex_lock(&mutex_associated_with_condition_variable);
while (!predicate)
    pthread_cond_wait(&condition_variable, mutex_associated_with_condition_variable);

注意:

  1. 必须锁定互斥锁。
  2. 在等待之前必须检查谓词(您正在等待的东西)。
  3. 等待必须在循环中。

违反这三个规则中的任何一个都会导致您遇到的问题。你的主要问题是你违反了第二条规则,即使你想要等待的事情已经发生了。

【讨论】:

  • 您可以编辑代码以显示如何操作吗?我明白你在说什么,它只是不能帮助我实现我的目标。我的理解也是 cond_wait 应该给 cpu 时间。所以如果你 while(0) 它没有。另外,如果您尝试获取锁,但失败了,它也会等待它,对吗?
  • @Lazik 好吧,我假设太多了。你根本没有得到条件变量。忘记你的代码。忘记你的问题。忘记我的回答。查找一些使用您理解的条件变量的示例代码。 while(0) 错误的原因是你必须等待 for 一些东西。
  • 是的,我希望可以,我正在寻找它 - 但找不到任何我想要的东西。这就是我在这里发帖的原因。也许我正在寻找的不是条件互斥范式。
  • @Lazik This 可能会对您有所帮助。不,它不会等待 cond_broadcast。广播通知线程它正在等待的事情可能已经发生,但它不可能是线程正在等待的事情,因为它必须有一个状态(事情发生了或者事情没有发生,所以两个状态)和条件变量是无状态的。
  • 如果你在等待某事,那么要么已经发生了,要么没有。并且无论是否发生了某事,都必须存储在某个地方,以便您知道是否等待。那东西叫做“谓词”,你必须实现它。条件变量的全部目的是提供一个原子的“解锁并等待”操作来修复事情发生的竞争条件,就像你试图等待它一样。如果这对您来说没有意义,那么您对条件变量的理解还不够好,无法使用它们编写代码。