- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试使用 pthreads 实现一个基本的工作线程池。场景是我想要固定数量的 worker ,他们在我的计划期间一直生活。
我永远不需要向单个线程发送信号,而是一次向所有线程发送信号,这就是我想要进行单个广播的原因。
在主程序继续之前,我需要等待所有线程完成,因此我决定在每个工作线程中使用 barrier_wait。
问题是,如果我的线程调用 barrier_wait,广播将不起作用。
完整示例和可编译代码如下所示。这只是为了广播的单一触发,在我的完整版本中,我会循环播放类似的内容
while(conditionMet){
1.prepare data
2.signal threads using data
3.post processing of thread results (because of barrier all threads finished)
4.modify conditionMet if needed
}
谢谢
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void checkResults(char *str,int i){
fprintf(stdout,"%s:%d\n",str,i);
}
void checkResults(char *str,size_t n,int i){
fprintf(stdout,"%s[%lu]:%d\n",str,n,i);
}
/* For safe condition variable usage, must use a boolean predicate and */
/* a mutex with the condition. */
int conditionMet = 0;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t barr;
#define NTHREADS 3
void *threadfunc(void *parm)
{
size_t i = (size_t) parm;
int rc;
rc = pthread_mutex_lock(&mutex);
checkResults("\tpthread_mutex_lock()",i, rc);
while (0==conditionMet) {
printf("\tThread blocked[%d]\n",(int)i);
rc = pthread_cond_wait(&cond, &mutex);
checkResults("\tpthread_cond_wait()",i, rc);
checkResults("\tbefore barrier",i);
rc = pthread_barrier_wait(&barr);//broadcast works if this is commented out
if(rc)
fprintf(stdout,"problems waiting for baarr\n");
checkResults("\tafter barrier",i);
}
rc = pthread_mutex_unlock(&mutex);
checkResults("\tpthread_mutex_lock()",i, rc);
return NULL;
}
int main(int argc, char **argv)
{
int rc=0;
int i;
pthread_t threadid[NTHREADS];
if(pthread_barrier_init(&barr, NULL,NTHREADS))
{
printf("Could not create a barrier\n");
}
printf("Enter Testcase - %s\n", argv[0]);
printf("Create %d threads\n", NTHREADS);
for(i=0; i<NTHREADS; ++i) {
rc = pthread_create(&threadid[i], NULL, threadfunc,(void *) i);
if(rc)
checkResults("pthread_create()", rc);
}
sleep(5); /* Sleep isn't a very robust way to serialize threads */
rc = pthread_mutex_lock(&mutex);
checkResults("pthread_mutex_lock()", rc);
/* The condition has occured. Set the flag and wake up any waiters */
conditionMet = 1;
printf("\nWake up all waiters...\n");
rc = pthread_cond_broadcast(&cond);
checkResults("pthread_cond_broadcast()", rc);
rc = pthread_mutex_unlock(&mutex);
checkResults("pthread_mutex_unlock()", rc);
printf("Wait for threads and cleanup\n");
for (i=0; i<NTHREADS; ++i) {
rc = pthread_join(threadid[i], NULL);
checkResults("pthread_join()", rc);
}
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
printf("Main completed\n");
return 0;
}
最佳答案
线程函数会在收到信号后立即锁定mutex
。因此,只有一个线程函数将在屏障上等待(mutex
仍处于锁定状态)并且永远不会满足屏障条件。
您应该重新设计应用程序的逻辑才能使用屏障。 mutex
必须在等待屏障之前立即解锁。此外,考虑到您的代码中使用了 pthread_cond_wait()
,您的应用程序中只会有一个线程处于事件状态,这完全消除了多线程的需要。
编辑:
我想详细说明一下最后一句话。假设我们像这样修改线程函数:
while (0==conditionMet) {
printf("\tThread blocked[%d]\n",(int)i);
rc = pthread_cond_wait(&cond, &mutex);
checkResults("\tpthread_cond_wait()",i, rc);
checkResults("\tbefore barrier",i);
pthread_mutex_unlock(&mutex); //added
rc = pthread_barrier_wait(&barr);//broadcast works if this is commented out
if(rc)
fprintf(stdout,"problems waiting for baarr\n");
checkResults("\tafter barrier",i);
}
这样我们就可以消除死锁,当只有一个线程能够到达屏障时 mutex
被锁定。但是在给定的时刻仍然只有一个线程会在临界区运行:当它的 pthread_cond_wait()
返回时 mutex
被锁定并且它将保持锁定状态直到线程函数到达_开锁(); _等待();一对。只有在下一个线程能够运行并到达其屏障之后。清洗、漂洗、重复……
OP prolly 想要的是让线程函数同时运行(否则为什么会有人想要线程池?)。在这种情况下,函数可能如下所示:
void *threadfunc(void *parm)
{
/*...*/
struct ThreadRuntimeData {
} rtd;
while (0==conditionMet) {
printf("\tThread blocked[%d]\n",(int)i);
rc = pthread_cond_wait(&cond, &mutex);
checkResults("\tpthread_cond_wait()",i, rc);
GetWorkData(&rtd); //Gets some data from critical section and places it in rtd
pthread_mutex_unlock(&mutex);
ProcessingOfData(&rtd); //here we do the thread's job
//without the modification of global data; this may take a while
pthread_mutex_lock(&mutex);
PublishProcessedData(&rtd); //Here we modify some global data
//with the results of thread's work.
//Other threads may do the same, so we had to enter critical section again
pthread_mutex_unlock(&mutex);
checkResults("\tbefore barrier",i);
rc = pthread_barrier_wait(&barr);//broadcast works if this is commented out
if(rc)
fprintf(stdout,"problems waiting for baarr\n");
checkResults("\tafter barrier",i);
}
/*...*/
}
这当然只是一个草图。线程函数的优化设计取决于OP希望线程做什么。
作为旁注,用于检查 pthread_barrier_wait()
返回结果的代码必须考虑到 PTHREAD_BARRIER_SERIAL_THREAD
返回。此外,将 conditionMet
声明为 volatile
会更安全。
关于c++ - 广播不适用于障碍,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8483174/
我正在尝试从标准输入中获取一行。据我所知,我们永远不应该使用gets的手册页中所说的gets: Never use gets(). Because it is impossible to tell w
很多问题SO和文章/书籍,例如https://mirrors.edge.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.201
我认为 Coffeescript 是一门很棒的语言!我正在寻找一些将静态分析添加到 Coffeescript 的项目/问题/功能。然而,经过一番搜索后,我发现 Coffeescript faq和 th
以下查询返回过去 12 个月(针对特定客户)每周的订单总量: SELECT DATEPART(year, orderDate) AS [year], DATEPART(month, or
我觉得这可能是一个错误,任何人都可以重现或看到我做事方式的一些错误。 我正在尝试将 GKPolygonObstacle 添加到 iOS 或 macOS Playground 中的 GKMeshGrap
我的 SKSpriteKit 应用程序中有一个单独的“Floor”类。当我第一次创建这个类时,我使用 在整个框架周围设置了一个屏障 self.physicsBody = SKPhysicsBody(e
我有我正在尝试建模的半连续数据(许多精确的零和连续的正结果)。我从 Zuur 和 Ieno 的 R 中零膨胀模型初学者指南中学到了大量关于零质量的建模数据,它区分了零膨胀 Gamma 模型和他们所描述
以下代码实现了一些无锁(且无原子!)的线程间通信,这些通信需要使用存储和加载内存屏障,但是C++ 11 release-acquire语义不适当,也不保证正确性。实际上,该算法暴露了对发布获取语义的某
我指的是在 https://developer.android.com/training/constraint-layout/index.html#constrain-to-a-barrier 上使用
我正在一个非常好的 IBM x 服务器(4 个 8 核 CPU)上运行一些模拟应用程序的 x64 版本。操作系统是 Linux - redhat 5.6 x64 内核。因此,此应用恰好在需要超过 2
我是一名优秀的程序员,十分优秀!