gpt4 book ai didi

c++ - pthread广播然后等待?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:55:03 25 4
gpt4 key购买 nike

我正在尝试设置多个线程处于等待状态,直到它们收到 pthread_cond_broadcast()

完成一项工作后,我希望线程回到它们的等待状态。

我还希望调用 pthread_cond_broadcast() 的进程在继续之前等待所有线程返回到它们的等待状态。在这种情况下,调用广播的是 main() 函数。我正在尝试让 main(0 在调用广播后执行 pthread_cond_wait()

void* Work::job(void* id)
{
int idx = (long)id;

while(1)
{
pthread_mutex_lock(&job_lock);

while(!jobs_complete)
{
// wait for main to broadcast
pthread_cond_wait(&can_work, &job_lock);
pthread_mutex_unlock(&job_lock);

// work here

pthread_mutex_lock(&job_lock);
++jobs_completed;

if(jobs_completed == NUM_THREADS)
{
jobs_complete = true;
pthread_cond_signal(&jobs_done);
pthread_mutex_unlock(&job_lock);
}
pthread_mutex_unlock(&job_lock);
}

pthread_mutex_unlock(&job_lock);
}

return NULL;
}

NUM_THREADS 是 4,job_lock 是一个 pthread_mutex_tcan_workjobs_donepthread_cond_tjobs_completed 是一个 booljobs_complete 是一个 int

// work

jobs_completed = false;
jobs_complete = 0;
pthread_mutex_lock(&job_lock);
pthread_cond_broadcast(&can_work);
pthread_cond_wait(&jobs_complete);
pthread_mutex_unlock(&job_lock);

// work that depends on jobs_complete

现在,我正在通过调用 pthread_cond_broadcast() 然后在它之后调用 pthread_cond_wait() 来执行此操作,但这似乎陷入了僵局。

任何人都可以解释我应该如何做或哪里出错了吗?如果有任何帮助,我将不胜感激。

谢谢!

最佳答案

我只是发布这个(这几乎是所有 C 代码,但 pthreads 也是如此,所以请稍微放松一下)来演示一种做我认为你正在尝试的事情的方法去完成。显然,您可能希望将其中的大部分内容正确地封装在适当的类等中。希望向您展示的是条件变量、互斥量以及它们与谓词管理和通知的关系是如何工作的。

希望您觉得它有用。祝你有美好的一天。

#include <iostream>
#include <unistd.h>
#include <pthread.h>
using namespace std;

// our global condition variable and mutex
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

// our predicate values.
bool finished = false;
int jobs_waiting = 0;
int jobs_completed = 0;

// our thread proc
static void *worker_proc(void* p)
{
intptr_t id = (intptr_t)p; // our id
size_t n_completed = 0; // our job completion count

// always latch prior to eval'ing predicate vars.
pthread_mutex_lock(&mtx);
while (!finished)
{
// wait for finish or work-waiting predicate
while (!finished && jobs_waiting == 0)
pthread_cond_wait(&cv, &mtx);

// we own the mutex, so we're free to look at, modify
// etc. the values(s) that we're using for our predicate
if (finished)
break;

// must be a job_waiting, reduce that number by one, then
// unlock the mutex and start our work. Note that we're
// changing the predicate (jobs_waiting is part of it) and
// we therefore need to let anyone that is monitoring know.
--jobs_waiting;
pthread_cond_broadcast(&cv);
pthread_mutex_unlock(&mtx);

// DO WORK HERE (this just runs a lame summation)
for (int i=0,x=0;i<1048576; x += ++i);
++n_completed;

// finished work latch mutex and setup changes
pthread_mutex_lock(&mtx);
++jobs_completed;
pthread_cond_broadcast(&cv);
}

// final report
cout << id << ": jobs completed = " << n_completed << endl;

// we always exit owning the mutex, so unlock it now. but
// let anyone else know they should be quitting as well.
pthread_cond_broadcast(&cv);
pthread_mutex_unlock(&mtx);
return p;
}

// sets up a batch of work and waits for it to finish.
void run_batch(int num)
{
pthread_mutex_lock(&mtx);
jobs_waiting = num;
jobs_completed = 0;
pthread_cond_broadcast(&cv);

// wait or all jobs to complete.
while (jobs_completed != num)
pthread_cond_wait(&cv, &mtx);

// we own this coming out, so let it go.
pthread_mutex_unlock(&mtx);
}

// main entry point.
int main()
{
// number of threads in our crew
static const size_t N = 7;
pthread_t thrds[N] = {0};

// startup thread crew.
intptr_t id = 0;
for (size_t i=0; i<N; ++i)
pthread_create(thrds + i, NULL, worker_proc, (void*)(++id));

// run through batches. each batch is one larger
// than the prior batch. this should result in some
// interesting job-counts per-thread.
for (int i=0; i<64; ++i)
run_batch(i);

// flag for shutdown state.
pthread_mutex_lock(&mtx);
finished = true;
pthread_cond_broadcast(&cv);
pthread_mutex_unlock(&mtx);
for (size_t i=0; i<N; pthread_join(thrds[i++], NULL));

return 0;
}

示例输出 #1

3: jobs completed = 256
6: jobs completed = 282
5: jobs completed = 292
2: jobs completed = 242
1: jobs completed = 339
4: jobs completed = 260
7: jobs completed = 409

示例输出 #2

6: jobs completed = 882
1: jobs completed = 210
4: jobs completed = 179
5: jobs completed = 178
2: jobs completed = 187
7: jobs completed = 186
3: jobs completed = 194

示例输出 #3

1: jobs completed = 268
6: jobs completed = 559
3: jobs completed = 279
5: jobs completed = 270
2: jobs completed = 164
4: jobs completed = 317
7: jobs completed = 159

固定批量大小

相同的代码,但改变了这个:

for (int i=0; i<64; ++i)
run_batch(i);

为此:

for (int i=0; i<64; ++i)
run_batch(N);

给出以下内容,这可能更接近您真正要找的内容。

示例输出 #1

4: jobs completed = 65
2: jobs completed = 63
5: jobs completed = 66
3: jobs completed = 63
1: jobs completed = 64
7: jobs completed = 63
6: jobs completed = 64

示例输出 #2

3: jobs completed = 65
5: jobs completed = 62
1: jobs completed = 67
7: jobs completed = 63
2: jobs completed = 65
6: jobs completed = 61
4: jobs completed = 65

示例输出 #3

2: jobs completed = 58
4: jobs completed = 61
5: jobs completed = 69
7: jobs completed = 68
3: jobs completed = 61
1: jobs completed = 64
6: jobs completed = 67

关于c++ - pthread广播然后等待?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15676027/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com