条件变量

条件变量本身不是锁,但是它仍然可以造成线程阻塞,它通常需要与互斥锁进行配合使用。

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条件变量

请自行百度

5.std::lock_guard和std::unique_lock的区别
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GarenJian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值