条件变量本身不是锁,但是它仍然可以造成线程阻塞,它通常需要与互斥锁进行配合使用。
1.linux接口函数
#include <pthread.h>
//初始化及销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//阻塞等待一个条件变量
//const struct timespec *restrict abstime是timepoint,不是time interval
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
/*
函数作用:
1.阻塞等待条件变量cond满足
2.释放已掌握的互斥锁
(1 2 两步为一个院子操作)
3.当被唤醒,函数返回时,解除阻塞并重新申请获取互斥锁
*/
//唤醒函数
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
为什么条件变量必须与互斥提配合使用?
阻塞等待和解锁必须是同一个原子性的操作,以确保 cond_wait 唤醒之前不会有其他线程获得这个互斥体对象。
2.实现生产者消费者
#include <iostream>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <deque>
#include <math.h>
#define MAX_NUM_OF_TASKS 30
std::deque<int> tasks;
pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_notempty = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_notfull = PTHREAD_COND_INITIALIZER;
int num = 0;
//消费者线程
void* consumer(void* param)
{
unsigned int thread_id = pthread_self();
while (true)
{
pthread_mutex_lock(&mutex_);
while (tasks.empty())
{
pthread_cond_wait(&cond_notempty, &mutex_);
}
int data = tasks.front();
tasks.pop_front();
std::cout << "消费者线程:" << thread_id << "消费了:" << data << "tasksize现在是:" << tasks.size() << std::endl;
pthread_mutex_unlock(&mutex_);
pthread_cond_signal(&cond_notfull);
sleep(rand() % 4);
}
return NULL;
}
//生产者线程
void* producer(void* param)
{
unsigned int pthread_id = pthread_self();
while (true)
{
pthread_mutex_lock(&mutex_);
while (tasks.size() == MAX_NUM_OF_TASKS)
{
pthread_cond_wait(&cond_notfull, &mutex_);
}
int numm = num;
tasks.push_back(num);
num++;
std::cout << "生产者线程:" << pthread_id << "生产了:" << numm << "tasksize现在是:" << tasks.size() << std::endl;
pthread_mutex_unlock(&mutex_);
pthread_cond_signal(&cond_notempty);
sleep(rand() % 3);
}
return NULL;
}
int main()
{
std::cout << "程序开始!!!" << std::endl;
int seed = time(NULL);
//创建6个消费者线程
pthread_t consumerthreadid[6];
for(int i = 0; i < 6; ++i)
{
pthread_create(&consumerthreadid[i], NULL, consumer, NULL);
}
//创建两个生产者线程
pthread_t producerthreadid[2];
for(int i = 0; i < 2; ++i)
{
pthread_create(&producerthreadid[i], NULL, producer, NULL);
}
for (int i = 0; i < 6; ++i)
{
pthread_join(consumerthreadid[i], NULL);
}
for (int i = 0; i < 2; ++i)
{
pthread_join(producerthreadid[i], NULL);
}
pthread_cond_destroy(&cond_notfull);
pthread_cond_destroy(&cond_notempty);
return 0;
}
附一段运行结果:
程序开始!!!
生产者线程:4056811264生产了:0tasksize现在是:1
生产者线程:4048357120生产了:1tasksize现在是:2
消费者线程:4107536128消费了:0tasksize现在是:1
消费者线程:4099081984消费了:1tasksize现在是:0
生产者线程:4056811264生产了:2tasksize现在是:1
消费者线程:4090627840消费了:2tasksize现在是:0
生产者线程:4048357120生产了:3tasksize现在是:1
消费者线程:4082173696消费了:3tasksize现在是:0
生产者线程:4048357120生产了:4tasksize现在是:1
生产者线程:4048357120生产了:5tasksize现在是:2
消费者线程:4073719552消费了:4tasksize现在是:1
消费者线程:4065265408消费了:5tasksize现在是:0
生产者线程:4056811264生产了:6tasksize现在是:1
消费者线程:4107536128消费了:6tasksize现在是:0
生产者线程:4048357120生产了:7tasksize现在是:1
消费者线程:4082173696消费了:7tasksize现在是:0
生产者线程:4056811264生产了:8tasksize现在是:1
生产者线程:4056811264生产了:9tasksize现在是:2
生产者线程:4056811264生产了:10tasksize现在是:3
消费者线程:4090627840消费了:8tasksize现在是:2
消费者线程:4090627840消费了:9tasksize现在是:1
消费者线程:4073719552消费了:10tasksize现在是:0
生产者线程:4048357120生产了:11tasksize现在是:1
生产者线程:4048357120生产了:12tasksize现在是:2
消费者线程:4073719552消费了:11tasksize现在是:1
生产者线程:4048357120生产了:13tasksize现在是:2
3.C++11关于条件变量及实现
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <functional>
#include <thread>
#include <deque>
#include <math.h>
#define MAX_NUM_OF_TASKS 30
std::mutex mutex_;
std::condition_variable cond_notempty;
std::condition_variable cond_notfull;
std::deque<int> tasks;
int num = 0;
void consumer(int i)
{
int num_thread = i;
while (true)
{
std::unique_lock<std::mutex> lock(mutex_);
cond_notempty.wait(lock, [=]{return !tasks.empty();});
int data = tasks.front();
tasks.pop_front();
std::cout << "第" << num_thread << "个消费者消费了: " << data << " 目前tasksize:" << tasks.size() << std::endl;
lock.unlock();
cond_notfull.notify_all();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void producer(int i)
{
int num_thread = i;
while (true)
{
std::unique_lock<std::mutex> lock(mutex_);
cond_notfull.wait(lock, [=]{return tasks.size() != MAX_NUM_OF_TASKS;});
int numm = num;
tasks.push_back(num);
num++;
std::cout << "第" << num_thread << "个生产者生产了: " << numm << " 目前tasksize:" << tasks.size() << std::endl;
lock.unlock();
cond_notempty.notify_one();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main()
{
std::cout << "程序开始!!!" << std::endl;
time(NULL);
std::thread consumerthreads[2];
for(int i = 0; i < 2; ++i)
{
consumerthreads[i] = std::thread(consumer, i + 1);
}
std::thread producerthreads[5];
for(int i = 0; i < 5; ++i)
{
producerthreads[i] = std::thread(producer, i + 1);
}
for(int i = 0; i < 2; ++i)
{
consumerthreads[i].join();
}
for(int i = 0; i < 5; ++i)
{
producerthreads[i].join();
}
return 0;
}
部分运行结果:
程序开始!!!
第1个生产者生产了: 0 目前tasksize:1
第2个生产者生产了: 1 目前tasksize:2
第2个消费者消费了: 0 目前tasksize:1
第1个消费者消费了: 1 目前tasksize:0
第4个生产者生产了: 2 目前tasksize:1
第5个生产者生产了: 3 目前tasksize:2
第3个生产者生产了: 4 目前tasksize:3
第2个生产者生产了: 5 目前tasksize:4
第1个生产者生产了: 6 目前tasksize:5
第3个生产者生产了: 7 目前tasksize:6
第5个生产者生产了: 8 目前tasksize:7
第4个生产者生产了: 9 目前tasksize:8
第1个消费者消费了: 2 目前tasksize:7
第2个消费者消费了: 3 目前tasksize:6
第2个生产者生产了: 10 目前tasksize:7
第1个生产者生产了: 11 目前tasksize:8
第3个生产者生产了: 12 目前tasksize:9
第2个消费者消费了: 4 目前tasksize:8
第1个消费者消费了: 5 目前tasksize:7
第4个生产者生产了: 13 目前tasksize:8
第5个生产者生产了: 14 目前tasksize:9
第2个生产者生产了: 15 目前tasksize:10
第1个生产者生产了: 16 目前tasksize:11
第3个生产者生产了: 17 目前tasksize:12
第1个消费者消费了: 6 目前tasksize:11
第5个生产者生产了: 18 目前tasksize:12
第2个消费者消费了: 7 目前tasksize:11
第4个生产者生产了: 19 目前tasksize:12
第2个生产者生产了: 20 目前tasksize:13
第1个生产者生产了: 21 目前tasksize:14
第3个生产者生产了: 22 目前tasksize:15
第2个消费者消费了: 8 目前tasksize:14
第4个生产者生产了: 23 目前tasksize:15
第5个生产者生产了: 24 目前tasksize:16
第1个消费者消费了: 9 目前tasksize:15
4.windows条件变量
请自行百度