所以我已经搜索了堆栈溢出和其他资源的高低,但我无法理解有关上述功能的一些事情。具体地,
1)当pthread_cond_timedwait()因计时器值用完而返回时,它如何自动重新获取互斥锁。互斥锁可能会被锁定在别处。例如,在生产者 - 消费者队列中,消费者可能正在使用timedwait()变体进行等待。从我读过的解释来看,当线程唤醒时,似乎会自动重新获取互斥锁。这让我感到困惑?或者是它会在计时器用完后唤醒,然后检查谓词并再次锁定。这没有意义吗?
2)当一堆线程获得了一个互斥体并且现在都在等待一个简单的pthread_cond_wait()时,如果另一个线程发出pthread_cond_broadcast()会发生什么。将每个线程(由调度程序确定)逐个唤醒,按顺序获取互斥锁,然后每个线程都继续执行?或者只会唤醒整个线程列表中的一个线程。我假设使用pthread_cond_signal()也可以使用后两种行为。此外,如果前面的方法是正确的行为,那么我们可以假设其他一些线程可能最终在其他地方调用变量wait()。那么那会将所有这些其他等待线程重新置于阻塞状态并等待信号。或者他们每个人都会继续醒来并逐一取得进步?
答案 0 :(得分:2)
(1) pthread_cond_timedwait()
简短(浅)解释它是如何工作的。
1)在调用函数之前,应锁定与pthread_cond_timewait()关联的互斥锁。这是你的责任。否则,函数行为未定义。
2)当程序将其控件转移到函数时,函数ATOMICALLY释放相关的互斥锁,使其他线程有机会获取它。等待时,互斥锁将解锁。解锁它是功能的责任。 如果函数实现无法执行,则只有一个线程处理相关的互斥锁。
3)当函数返回时,无论是由于超时还是由于接收到信号,函数ATOMICALLY都会锁定互斥锁。锁定互斥锁是功能的责任。
4)现在你应该再次解锁互斥锁。
解释中的“原子”一词意味着函数本身是线程安全的。
(2) pthread_cond_broadcast()
使用pthread_cond_broadcast()进行信号传递会导致所有等待的线程被唤醒并逐个开始处理。使用pthread_cond_signal()发送信号只会唤醒一个线程。要“感觉”这个概念,您可以使用以下代码来说明这个想法。用pthread_cond_brodcast替换pthread_cons_signal。考虑到当使用pthread_cons_signal时程序永远不会终止:只有一个服务员线程获取信号并从等待循环中逃脱。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int value = 0;
void* waiter(void* arg)
{
int* tid = (int*)arg;
printf("waiter started %d\n", *tid);
pthread_mutex_lock(&mutex);
while(value == 0)
{
pthread_cond_wait(&cond, &mutex);
}
sleep(10);
printf("waiter %d releases\n", *tid);
pthread_mutex_unlock(&mutex);
}
void* notifier(void* arg)
{
sleep(2);
pthread_mutex_lock(&mutex);
value = 1;
//pthread_cond_broadcast(&cond);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
int main(void)
{
pthread_t w1; // waiter
int tid1=1;
pthread_t w2; // waiter
int tid2=2;
pthread_t n1; // notifier
pthread_create(&w1, NULL, waiter, &tid1);
pthread_create(&w2, NULL, waiter, &tid2);
pthread_create(&n1, NULL, notifier, NULL);
pthread_join(w1, NULL);
pthread_join(w2, NULL);
pthread_join(n1, NULL);
return 0;
}
答案 1 :(得分:1)
如果pthread_cond_timedwait()
由于超时到期而返回,它将在返回之前重新获取互斥锁。这可能意味着它必须等待互斥锁解锁,如果它在那时被另一个线程锁定。从本质上讲,它的行为就像在返回之前调用pthread_mutex_lock()
一样。
当调用pthread_cond_broadcast()
时,所有等待的线程都将被唤醒,这意味着它们都会尝试获取互斥锁并返回。当然,互斥锁会对此进行序列化,因此它们只能一次返回一次。在此之后发生的事情并不重要 - 这些线程一旦获得互斥锁,就会最终从pthread_cond_wait()
调用返回。另一个调用pthread_cond_wait()
的线程不会影响这一点。