首先看一个生产者和消费者实例,主线程作为生产者,它先创建很多消费者线程,再给队列中放入产品
#include <bits/stdc++.h>
#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
using namespace st d;
static pthread_mutex_t g_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER;
static queue<int> g_queue;
static void *thread_func(void *arg)
{
pthread_mutex_lock(&g_mtx);
while (g_queue.empty())
{
pthread_cond_wait(&g_cond, &g_mtx);
}
int val = g_queue.front();
g_queue.pop();
cout << "ThreadID:" << pthread_self() << " Get front queue:" << val << endl;
pthread_mutex_unlock(&g_mtx);
return 0;
}
int main()
{
int threadNum = 10;
pthread_t tids[threadNum];
int maxNum = 10;
for (int i = 0; i < threadNum; i++)
{
pthread_create(tids + i, NULL, thread_func, NULL);
}
for (int i = 0; i < maxNum; i++) //主线程作为生产者
{
pthread_mutex_lock(&g_mtx);
g_queue.push(i);
pthread_cond_signal(&g_cond);
pthread_mutex_unlock(&g_mtx);
}
for (int i = 0; i < threadNum; i++) //主线程执行完回收
{
pthread_join(tids[i], NULL);
}
cout << "Main exit!" << endl;
return 0;
}
运行结果:
ThreadID:139923478742784 Get front queue:0
ThreadID:139923554830080 Get front queue:1
ThreadID:139923546375936 Get front queue:2
ThreadID:139923537921792 Get front queue:3
ThreadID:139923529467648 Get front queue:4
ThreadID:139923521013504 Get front queue:5
ThreadID:139923512559360 Get front queue:6
ThreadID:139923504105216 Get front queue:7
ThreadID:139923495651072 Get front queue:8
ThreadID:139923487196928 Get front queue:9
Main exit!
可以看到条件变量主要用于共享数据状态变化的通信, 当一个线程依赖于另一个线程,而另一个线程对它们的共享数据做了改变后,通知激活这个线程。
条件变量是与互斥量相关联的一种用于多线程之间关于共享数据状态改变的通信机制。需要和互斥锁配合使用,防止多个线程同时请求
pthread_cond_wait
的静态条件,mutex互斥锁必须是普通锁
PTHREAD_MUTEX_TIMED_NP
或者适应锁
PTHREAD_MUTEX_ADAPTIVE_NP
。
调用
pthread_cond_wait
前必须由本线程加锁,调用
pthread_cond_wait
时,有两个操作:1. 调用线程放到条件等待队列上。2. Mutex解锁。因为只有解锁了,生产者线程才能去改变条件。而这两步必须是原子操作不可分割,然后多个线程进入条件等待队列,当有另一个线程调用
pthread_cond_signal
时,
pthread_cond_wait
获得mutex后返回,这里只有一个线程获取了mutex,其他线程依旧是
pthread_cond_wait
状态,这次加锁刚好对应了在
pthread_cond_wait
之前的加锁动作。
激发条件是:
pthread_cond_signal
激活一个等待该条件的线程,存在多个等待线程时
按入队顺序
激活其中一个;而
pthread_cond_broadcast
则激活所有等待线程。