C++中的条件变量pthread_cond

条件变量的作用

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

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

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

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

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

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

#include 
#include 

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);

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

你可能感兴趣的:(c++,开发语言)