1. pthread_cond_broadcast
pthread_cond_broadcast是一个函数,用于向所有等待在特定条件变量上的线程发送信号,以唤醒它们。它是POSIX线程库中的一部分,用于线程间的同步。
当某个线程调用`pthread_cond_broadcast`函数时,它会通知所有等待在该条件变量上的线程,使它们从等待状态转换为可运行状态。这些线程可以继续执行它们的任务。pthread_cond_broadcast`函数的原型如下:
#include <pthread.h>
int pthread_cond_broadcast(pthread_cond_t *cond);
其中,`cond`是一个指向条件变量的指针。调用`pthread_cond_broadcast`函数时,需要确保已经对条件变量进行了正确的初始化。
2. 需要注意的是,`pthread_cond_broadcast`函数并不会阻塞调用它的线程,它只是发送信号给等待在条件变量上的线程。因此,当调用pthread_cond_broadcast
函数时,它会唤醒所有等待在条件变量上的线程,但并不保证它们会立即执行。线程的执行顺序和调度是由操作系统决定的。
通常情况下,pthread_cond_broadcast
函数与pthread_cond_wait
函数一起使用,用于实现线程间的同步。当某个线程调用pthread_cond_wait
函数时,它会进入等待状态,并释放对应的互斥锁。当其他线程调用pthread_cond_broadcast
函数时,等待在条件变量上的线程会被唤醒,并尝试重新获取互斥锁,从而继续执行。
下面是一个简单的示例代码,演示了pthread_cond_broadcast
函数的使用:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
int count = 0;
void* thread_func(void* arg) {
int is_wait = 0;
pthread_mutex_lock(&mutex);
count++;
if (count == 5) {
//printf("[%d]本线程不等待,条件满足唤醒其他线程,然后直接返回\n", count);
pthread_cond_broadcast(&cond);
} else {
is_wait = 1;
printf("本线程条件不满足,即将进入线程等待\n");
pthread_cond_wait(&cond, &mutex);
}
if (is_wait) {
printf("本线程曾经等待过,现在被唤醒了,继续执行\n");
} else {
printf("本线程不等待,条件满足唤醒了其他线程后,直接返回\n");
}
pthread_mutex_unlock(&mutex);
// 线程继续执行其他操作
return NULL;
}
int main() {
pthread_t threads[5];
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
for (int i = 0; i < 5; i++) {
pthread_create(&threads[i], NULL, thread_func, NULL);
}
//sleep(5);
// 等待所有线程结束
for (int i = 0; i < 5; i++) {
pthread_join(threads[i], NULL);
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
在上面的示例中,我们创建了5个线程,并且每个线程都会递增count
变量的值。当count
的值达到5时,其中一个线程会调用pthread_cond_broadcast
函数,通知其他等待在条件变量上的线程。并把他们唤醒继续执行,上面的例子将打印:
[1]本线程条件不满足,即将进入线程等待
[2]本线程条件不满足,即将进入线程等待
[3]本线程条件不满足,即将进入线程等待
[4]本线程条件不满足,即将进入线程等待
本线程不等待,条件满足直接返回
本线程曾经等待过,现在被唤醒了,继续执行
本线程曾经等待过,现在被唤醒了,继续执行
本线程曾经等待过,现在被唤醒了,继续执行
本线程曾经等待过,现在被唤醒了,继续执行
需要注意的是,线程在进入pthread_cond_wait的时候,会自动释放互斥锁,请知!
2. pthread_cond_signal
另外一种情况是,我们可以使用pthread_cond_signal()函数随机唤醒一个等待的线程:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 5
int global_var = 0; // 全局变量
pthread_mutex_t mutex; // 互斥锁
pthread_cond_t cond_var; // 条件变量
void* thread_function(void* arg) {
int thread_id = *((int*)arg);
// 等待条件变量
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond_var, &mutex);
// 打印全局变量
printf("线程 %d: global_var = %d\n", thread_id, global_var);
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
int thread_ids[NUM_THREADS];
// 初始化互斥锁和条件变量
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond_var, NULL);
// 创建线程
for (int i = 0; i < NUM_THREADS; i++) {
thread_ids[i] = i + 1;
pthread_create(&threads[i], NULL, thread_function, (void*)&thread_ids[i]);
}
// 模拟一些工作
sleep(2);
// 修改全局变量并唤醒一个线程
pthread_mutex_lock(&mutex);
global_var = 42; // 修改全局变量
pthread_cond_signal(&cond_var); // 唤醒一个等待的线程
pthread_mutex_unlock(&mutex);
// 等待所有线程结束
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
// 清理资源
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond_var);
return 0;
}
使用 pthread_cond_signal
唤醒的是一个正在等待该条件变量的线程,但并不保证是特定的哪个线程。具体来说,操作系统会选择一个等待的线程来唤醒,这个选择通常是随机的,取决于线程的调度策略和状态。
详细说明:
- 线程的等待:当多个线程调用
pthread_cond_wait
并进入等待状态时,它们会被放入一个等待队列。 - 唤醒机制:当调用
pthread_cond_signal
时,操作系统会从这个等待队列中选择一个线程进行唤醒。这个选择是非确定性的,可能是第一个等待的线程,也可能是其他线程,具体取决于操作系统的调度策略。 - 线程的调度:唤醒的线程在被唤醒后会尝试重新获取与条件变量关联的互斥锁。如果成功获取锁,它将继续执行;如果未能获取锁,则会继续等待。
因此,使用 pthread_cond_signal
时,无法预测具体会唤醒哪个线程。