- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个工作线程池。每个 worker 执行这个例程:
void* worker(void* args){
...
pthread_mutex_lock(&mtx);
while (queue == NULL && stop == 0){
pthread_cond_wait(&cond, &mtx);
}
el = pop(queue);
pthread_mutex_unlock(&mtx);
...
}
主线程:
int main(){
...
while (stop == 0){
...
pthread_mutex_lock(&mtx);
insert(queue, el);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mtx);
...
}
...
}
然后我有一个信号处理程序,它在收到信号时执行此代码:
void exit_handler(){
stop = 1;
pthread_mutex_lock(&mtx);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mtx);
}
我省略了声明和初始化,但原始代码有它们。
大部分时间收到信号后一切正常,但有时似乎某些工作线程停留在等待循环中,因为它们没有看到变量 stop 发生变化和/或它们没有被唤醒广播。
所以线程永远不会结束。我缺少什么?
编辑:stop=1 移入了 exit_handler 的关键部分。问题依然存在。
EDIT2:我正在使用 Ubuntu 的虚拟机上执行该程序。由于代码看起来完全正确,我尝试更改 VM 和操作系统 (XUbuntu),现在它似乎可以正常工作。仍然不知道为什么,有人有想法吗?
最佳答案
这里有些猜测,但是评论太长了,所以如果有错,我会删除。我认为您可能对 pthread_cond_broadcast
的工作原理有误解(至少我过去一直被它困扰)。来自man page :
The
pthread_cond_broadcast()
function shall unblock all threads currently blocked on the specified condition variable cond.
好的,这是有道理的,_broadcast
唤醒当前阻塞在 cond
上的所有线程。 但是,只有一个被唤醒的线程在全部被唤醒后能够锁定互斥体。同样来自手册页:
The thread(s) that are unblocked shall contend for the mutex according to the scheduling policy (if applicable), and as if each had called
pthread_mutex_lock()
.
所以这意味着如果 3 个线程在 cond
上被阻塞并且 _broadcast
被调用,所有 3 个线程都会被唤醒,但只有 1 个线程可以获取互斥量。另外 2 个仍将停留在 pthread_cond_wait
中,等待信号。因此,他们看不到 stop
设置为 1,并且 exit_handler
(我假设是 Ctrl+c 软件信号?)完成信号,所以剩下的输掉 _broadcast
竞争的线程陷入困境,等待永远不会到来的信号,并且无法读取已设置的 stop
标志。
我认为有 2 个选项可以解决/解决这个问题:
pthread_cond_timedwait
.即使没有收到信号,这也会在指定的时间间隔从等待返回,看到 stop == 1
,然后退出。worker
函数的末尾添加 pthread_cond_signal
或 pthread_cond_broadcast
。这样,就在线程退出之前,它将向 cond
变量发出信号,允许任何其他等待的线程获取互斥锁并完成处理。如果没有线程在等待条件变量,则向它发送信号没有任何坏处,因此即使对于最后一个线程也应该没问题。编辑:这是一个 MCVE 证明(据我所知)我上面的回答是错误的,呵呵。只要我按下 Ctrl+c,程序就会“立即”退出,这对我来说意味着所有线程在广播后迅速获取互斥锁,看到 stop
为假,然后退出。然后 main
加入线程并结束进程。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <signal.h>
#include <unistd.h>
#define NUM_THREADS 3
#define STACK_SIZE 10
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c = PTHREAD_COND_INITIALIZER;
volatile bool stop = false;
int stack[STACK_SIZE] = { 0 };
int sp = 0; // stack pointer,, also doubles as the current stack size
void SigHandler(int sig)
{
if (sig == SIGINT)
{
stop = true;
}
else
{
printf("Received unexcepted signal %d\n", sig);
}
}
void* worker(void* param)
{
long tid = (long)(param);
while (stop == false)
{
// acquire the lock
pthread_mutex_lock(&m);
while (sp <= 0) // sp should never be < 0
{
// there is no data in the stack to consume, wait to get signaled
// this unlocks the mutex when it is called, and locks the
// mutex before it returns
pthread_cond_wait(&c, &m);
}
// when we get here we should be guaranteed sp >= 1
printf("thread %ld consuming stack[%d] = %d\n", tid, sp-1, stack[sp-1]);
sp--;
pthread_mutex_unlock(&m);
int sleepVal = rand() % 10;
printf("thread %ld sleeping for %d seconds...\n", tid, sleepVal);
sleep(sleepVal);
}
pthread_exit(NULL);
}
int main(void)
{
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
srand(time(NULL));
for (long i=0; i<NUM_THREADS; i++)
{
int rc = pthread_create(&threads[i], &attr, worker, (void*)i);
if (rc != 0)
{
fprintf(stderr, "Failed to create thread %ld\n", i);
}
}
while (stop == false)
{
// produce data in bursts
int numValsToInsert = rand() % (STACK_SIZE - sp);
printf("main producing %d values\n", numValsToInsert);
// acquire the lock
pthread_mutex_lock(&m);
for (int i=0; i<numValsToInsert; i++)
{
// produce values for the stack
int val = rand() % 10000;
// I think this should already be guaranteed..?
if (sp+1 < STACK_SIZE)
{
printf("main pushing stack[%d] = %d\n", sp, val);
stack[sp++] = val;
// signal the workers that data is ready
//printf("main signaling threads...\n");
//pthread_cond_signal(&c);
}
else
{
printf("stack full!\n");
}
}
pthread_mutex_unlock(&m);
// signal the workers that data is ready
printf("main signaling threads...\n");
pthread_cond_broadcast(&c);
int sleepVal = 1;//rand() % 5;
printf("main sleeping for %d seconds...\n", sleepVal);
sleep(sleepVal);
}
for (long i=0; i<NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
关于c - 为什么有些线程没有收到 pthread_cond_broadcast?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49200530/
我有一个工作线程池。每个 worker 执行这个例程: void* worker(void* args){ ... pthread_mutex_lock(&mtx); while (que
根据我昨天的问题,here ,我编写了一个小代码示例,它启动了一些计数和一些等待线程。等待线程将停止 pthread_cond_wait 直到收到信号。计数线程完成任务后发送信号。 等待线程接收信号,
我正在使用 POSIX,并且有 3 个线程。 请注意下面的所有线程都使用相同的互斥锁。 线程 1 正在使用 pthread_cond_wait 等待满足条件(等待在 while 循环内,因此也不是无条
我想从主线程向等待条件的所有其他线程发送广播信号。在我看来,广播信号来得早。 #include #include #define NUM 4 #define SIZE 256 using name
我真的很难理解如何以允许线程同时运行的方式锁定和解锁互斥体。现在我试图让每个线程都做一些事情,然后等到所有线程都准备好,然后重复它。这应该反复发生,所以我把它都放在一个条件循环中。我的问题是,似乎我的
我写了这个程序: pthread_cond_t placeFootCondition; pthread_mutex_t rf,lf; void* rss(void* in){ while(1)
假设广播线程在只有 3 个线程等待时进行广播,并且在广播线程完成广播后第 4 个线程调用 pthread_cond_wait,第 4 个线程是否会脱离等待状态。以及如何重置条件变量,以便广播线程有时可
对于 pthread_cond_t,我们必须关联一个互斥体,当发出条件信号时,我看到了如下代码 pthread_mutex_lock(&mutex); //code that makes condit
在 linux 2.6.30 中使用 pthreads 我试图发送一个信号,这将导致多个线程开始执行。广播似乎只被一个线程接收到。我已经尝试过 pthread_cond_signal 和 pthrea
我有一个带有“管理器”线程的简单应用程序,它产生十个简单的“工作器”线程。我希望所有“工作”线程都阻塞在同一个条件变量(即:condvar)上,并且我希望通过 pthread_cond_broadca
我想使用 pthread_cond_broadcast() 唤醒所有等待相同条件的线程。 但是,这些线程似乎不能真正并行运行,因为它们必须共享相同的互斥体。 我说的对吗?或者有什么办法吗? 提前致谢。
所以我搜索了关于堆栈溢出和其他资源的高低,但我无法理解与上述功能有关的一些事情。具体来说, 1)当pthread_cond_timedwait()因为定时器值用完而返回时,它如何自动重新获取互斥量。互
如果我调用 pthread_cond_broadcast 并且没有人在等待条件,pthread_cond_broadcast 是否会调用上下文切换和/或调用内核? 如果不是,我可以依靠它非常快吗(我的
我有一个“服务器”进程a,可能还有多个“客户端”进程b。服务器创建一个共享内存文件 (shm_open),其中包含一个 pthread_mutex_t 和一个 pthread_cond_t,用于向客户
由于 pthread_cond_broadcast 的 pthread 示例唤醒是稀疏的,我写了一个,但不确定这是否正确同步以及如何做到这一点: 所有线程是否共享相同的 c 和 mtx 变量? 是否需
我有一个结构数组。每个结构体如下。 struct thread_st { pthread_t thr; int conn; pthread_mutex_t mutex;
我是多线程新手,遇到了段错误。我正在使用 void addfunction(void *xyz) { flag_TO_go = 1; pthread_cond_broadcast(&c
条件变量通常用于在互斥量下修改它们所指的状态。然而,当状态只是一个单一的只设置标志时,就不需要互斥锁来阻止同时执行。所以有人可能想做这样的事情: flag = 1; pthread_cond_broa
在我的程序中有一部分代码等待被其他部分代码唤醒: 这是进入休眠的部分: void flush2device(int task_id) { if (pthread_mutex_lock(&id2cvLo
我正在尝试使用 LD_PRELOAD 机制插入对 pthread_cond_broadcast 的调用。我插入的 pthread_cond_broadcast 函数只是调用原始的 pthread_co
我是一名优秀的程序员,十分优秀!