C++中的条件变量pthread_cond

条件变量的作用

条件变量(pthread_cond)是 C++ 多线程编程中的一种同步机制。它通常与互斥量(pthread_mutex)结合使用,用于实现线程间的协调与同步。

条件变量的作用是使线程能够等待某个条件的发生,并在条件满足时被唤醒。条件变量可以用来避免线程轮询等待某个事件的发生,从而提高线程的效率。

条件变量通常与互斥量一起使用。一个线程在等待某个条件时,它会先释放互斥量,然后进入等待状态。当另一个线程满足了这个条件,它会通过发送信号或广播信号的方式通知等待的线程,使得它从等待状态中醒来并重新获得互斥量,然后继续执行。

为什么需要将条件变量和互斥量一起使用

条件变量和互斥量在 C++ 多线程编程中经常一起使用,主要是为了保证线程安全和避免竞态条件等问题
互斥量是一种用于保护共享资源的同步原语,用于防止多个线程同时访问共享资源而引起的竞争条件等问题。线程在访问共享资源之前需要获取互斥量,防止其他线程同时访问同一共享资源,从而保证线程安全。
条件变量则用于在线程之间传递信号和通知。线程在等待某个条件变量时,会先释放已经获取的互斥量,并进入等待状态。在等待期间,线程会阻塞并不占用 CPU 资源,直到有另一个线程发送信号或广播信号的时候,线程才会被唤醒,重新获得互斥量,并检查条件是否满足,从而决定是继续等待还是执行后续操作。
将条件变量和互斥量结合使用可以避免竞态条件和死锁等问题。在使用条件变量时,线程需要先获取互斥量,以确保线程安全。否则,在多线程环境下,可能会出现竞争条件等问题。同时,在等待条件变量时,线程需要先释放已经获取的互斥量,以避免死锁等问题。
因此,条件变量和互斥量的结合使用,可以使多线程程序更加安全和可靠。

下面是一个简单的例子,展示了条件变量的使用:

#include <pthread.h>
#include <iostream>

using namespace std;

pthread_mutex_t mutex;
pthread_cond_t cond;

int num = 0;	//临界区

void* thread_func1(void* arg) {		//线程1的main函数
    pthread_mutex_lock(&mutex);
    
    //在访问临界区资源之前先对互斥量解锁,访问或者修改完之后解锁
    num++;
    cout << "Thread1: num=" << num << endl;
    pthread_cond_signal(&cond);
    
    pthread_mutex_unlock(&mutex);
}

void* thread_func2(void* arg) {		//线程2的main函数
    pthread_mutex_lock(&mutex);
    
    while (num == 0) {				//当num==0时阻塞,在函数pthread_cond_wait内部会先释放mutex(不释放可能会导致死锁),当线程1发送信号之后线程2会从等待状态中醒来,继续向下执行
        pthread_cond_wait(&cond, &mutex);
    }
    num--;
    cout << "Thread2: num=" << num << endl;
    
    pthread_mutex_unlock(&mutex);
}

int main() {
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, thread_func1, NULL);
    pthread_create(&thread2, NULL, thread_func2, NULL);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

在这个例子中,我们创建了两个线程 thread1 和 thread2。其中,thread1 会先执行,它会将 num 的值加 1,并通过 pthread_cond_signal() 函数通知等待的线程。线程 thread2 在等待 num 的值变为非零的同时,通过 pthread_cond_wait() 函数进入等待状态。当线程 thread1 发送信号后,线程 thread2 会从等待状态中醒来,并执行 num 的减 1 操作。

注意,在等待条件变量时,线程需要先获取互斥量,以确保线程安全。否则,在多线程环境下,可能会出现竞争条件等问题。

主要函数

pthread_cond_t;      //条件变量类型
int pthread_cond_init(pthread_cond_t * restrict cond, const pthread_condattr_t * restrict attr);    
					 //初始化一个条件变量
int pthread_cond_destroy(pthread_cond_t * restrict cond);        //销毁一个条件变量
int pthread_cond_wait(pthread_cond_t * restrict cond, const pthread_mutexr_t * restrict mutex);
					//函数的作用是将线程置于等待状态,并且在等待期间会释放 mutex 互斥量的锁,当线程被唤醒之后在重新取得互斥量的锁
int pthread_cond_timewait(pthread_cond_t * restrict cond, const pthread_mutexr_t * restrict mutex, const struct timespec *restrict abstime);		    //限时等待一个条件变量
int pthread_cond_signal(pthread_cond_t * restrict cond);		//唤醒至少一个阻塞在条件变量上的线程
int pthread_cond_broadcast(pthread_cond_t * restrict cond);		//唤醒全部阻塞在条件变量上的线程

使用条件变量的一般步骤如下:

  1. 定义互斥量和条件变量:
pthread_mutex_t mutex;
pthread_cond_t cond;
  1. 初始化互斥量和条件变量:
pthread_mutex_init(&mutex, NULL);	//NULL使用默认的属性
pthread_cond_init(&cond, NULL);

  1. 在等待条件的线程中,获取互斥量,并进入等待状态:
pthread_mutex_lock(&mutex);
while (条件不满足) {
    pthread_cond_wait(&cond, &mutex);
}

**在等待条件变量时,线程需要先获取互斥量,以确保线程安全。**如果条件不满足,则线程调用 pthread_cond_wait() 函数进入等待状态,并释放已经获取的互斥量。在等待期间,线程会阻塞并不占用 CPU 资源。

  1. 在满足条件的线程中,获取互斥量,并发送信号或广播信号:
pthread_mutex_lock(&mutex);
// 满足条件后,发送信号或广播信号
pthread_cond_signal(&cond); // 或者 pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);

在满足条件后,线程需要获取互斥量,并通过 pthread_cond_signal() 函数发送信号或通过 pthread_cond_broadcast() 函数广播信号。发送信号后,等待条件的线程将会从等待状态中醒来,并重新获得互斥量,以便执行后续操作。

  1. 在所有线程结束后,销毁互斥量和条件变量:
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);

注意,条件变量的使用需要和互斥量结合使用,以避免竞态条件等问题。在等待条件变量时,线程需要先获取互斥量,以确保线程安全。否则,在多线程环境下,可能会出现竞争条件等问题。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是一个使用pthread_cond_wait()和pthread_cond_signal()的例子: ```c++ #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define NUM_THREADS 2 pthread_mutex_t mutex; pthread_cond_t cond; int count = 0; void *func1(void *arg) { pthread_mutex_lock(&mutex); while(count < 10) { if(count % NUM_THREADS == 0) { printf("Thread 1: count = %d\n", count); count++; pthread_cond_signal(&cond); } else { pthread_cond_wait(&cond, &mutex); } } pthread_mutex_unlock(&mutex); pthread_exit(NULL); } void *func2(void *arg) { pthread_mutex_lock(&mutex); while(count < 10) { if(count % NUM_THREADS == 1) { printf("Thread 2: count = %d\n", count); count++; pthread_cond_signal(&cond); } else { pthread_cond_wait(&cond, &mutex); } } pthread_mutex_unlock(&mutex); pthread_exit(NULL); } int main() { pthread_t threads[NUM_THREADS]; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); pthread_create(&threads[0], NULL, func1, NULL); pthread_create(&threads[1], NULL, func2, NULL); for(int i=0; i<NUM_THREADS; i++) { pthread_join(threads[i], NULL); } pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); return 0; } ``` 这个例子,我们创建了两个线程,func1()和func2()。这两个线程都会尝试对count变量进行操作,但是它们必须轮流访问count。当count是偶数时,func1()会递增它,当count是奇数时,func2()会递增它。在每次递增后,线程会发送信号来通知另一个线程它可以开始执行。如果另一个线程当前不能执行,它会等待信号。当count达到10时,线程就会退出。 在这个例子,pthread_cond_wait()的作用是让线程等待信号,而pthread_cond_signal()的作用是发送信号。这样,我们可以实现线程之间的同步,并且避免了busy waiting。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值