线程同步——条件变量

        当我们需要控制对内存资源的存取的时候,可以用一种简单的加锁的方法来控制,即互斥锁。但互斥锁有一个明显的缺点,就是它只有两个状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补来互斥锁的不足。条件变量通常和互斥锁一起使用。

        【使用过程】

        1.调用pthread_mutex_init()函数来初始化一个pthread_t类型的互斥锁

           调用pthread_cond_init()函数来初始化一个pthread_cond_t类型的条件变量

        2.创建线程

        3.一个线程先调用pthread_mutex_lock()函数给互斥锁上锁,再调用无条件等待函数pthread_cond_wait()或者计时等待函数pthread_cond_timedwait()等待条件变量为真。调用此函数后,会先解锁,阻塞等待到信号后,再上锁并继续执行。此时再调用pthread_mutex_unlock()函数给互斥锁解锁。

        4.另一个线程调用pthread_cond_signal()函数唤醒对应条件变量的一个线程(多个线程则按入队顺序唤醒),或者调用pthread_cond_broadcast()函数唤醒对应条件变量的所以线程。

        【应用举例】

        描述:三个进程,一个加加,一个输出偶数,一个输出奇数

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

pthread_cond_t cond;
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;

int flag = 0;
int n;

/***********
*全局变量n加1
***********/
void *number()
{
	while (1)
	{
		if (flag == 0)
		{
			n++;
			flag = 1;
		}
		pthread_cond_signal(&cond);      //发送信号
	}
}

/********
*输出偶数
********/
void *even()
{
	while (1)
	{
		pthread_mutex_lock(&mutex1);
		
		if (flag == 1)
		{
			//阻塞等待信号
			pthread_cond_wait(&cond, &mutex1);

			if (n%2 == 0)
			{
				printf("even n = %d\n", n);
				sleep(1);
				flag = 0;
			}
		}

		pthread_mutex_unlock(&mutex1);
	}
}

/********
*输出奇数
********/
void *odd()
{
	while (1)
	{
		pthread_mutex_lock(&mutex2);
		
		if (flag == 1)
		{
			//阻塞等待条件变量为真
			pthread_cond_wait(&cond, &mutex2);
			if (n%2 == 1)
			{
				printf("odd  n = %d\n", n);
				sleep(1);
				flag = 0;
			}			
		}

		pthread_mutex_unlock(&mutex2);
	}
}

int main()
{
	pthread_t tid1, tid2, tid3;
	int ret;

	pthread_mutex_init(&mutex1, NULL);//锁1初始化
	pthread_mutex_init(&mutex2, NULL);//锁2初始化
	pthread_cond_init(&cond, NULL);   //初始化条件变量cond,条件变量为假

	ret = pthread_create(&tid1, NULL, number, NULL);//创建线程1:n++
	if (ret < 0)
	{
		perror("pthread_create");
		exit(1);
	}

	ret = pthread_create(&tid2, NULL, even, NULL);//创建线程2:输出偶数
	if (ret < 0)
	{
		perror("pthread_create");
		exit(1);
	}

	ret = pthread_create(&tid3, NULL, odd, NULL); //创建线程3:输出奇数
	if (ret < 0)
	{
		perror("pthread_create");
		exit(1);
	}

	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	pthread_join(tid3, NULL);

	pthread_mutex_destroy(&mutex1);
	pthread_mutex_destroy(&mutex2);

	pthread_cond_destroy(&cond);

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C++ 中,我们可以使用线程库来实现多线程编程。线程的挂起、唤醒与终止是多线程编程中非常重要的一部分。 线程的挂起也称为线程的休眠,它可以让线程停止运行一段时间,等待某个条件满足后再继续运行。在 C++ 中,我们可以使用 std::this_thread::sleep_for() 函数来实现线程的挂起,该函数可以让当前线程挂起一段时间,例如: ```cpp #include <chrono> #include <thread> int main() { // 挂起当前线程 1 秒钟 std::this_thread::sleep_for(std::chrono::seconds(1)); return 0; } ``` 线程的唤醒可以通过条件变量来实现,条件变量是一种同步机制,用于在线程之间传递信号。在 C++ 中,我们可以使用 std::condition_variable 类来创建条件变量,然后使用 wait() 函数来挂起线程等待条件变量的信号,使用 notify_one() 函数来唤醒一个等待条件变量的线程,例如: ```cpp #include <condition_variable> #include <mutex> #include <thread> std::condition_variable cv; std::mutex mtx; bool ready = false; void worker_thread() { // 等待条件变量的信号 std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, [](){ return ready; }); // 条件满足后继续执行 // ... } int main() { // 唤醒等待条件变量的线程 { std::lock_guard<std::mutex> lock(mtx); ready = true; } cv.notify_one(); return 0; } ``` 线程的终止可以使用 std::thread::join() 函数来实现,该函数可以让当前线程等待另一个线程执行完成后再继续执行,例如: ```cpp #include <thread> void worker_thread() { // ... } int main() { std::thread t(worker_thread); // 等待 worker_thread 执行完成 t.join(); return 0; } ``` 另外,线程的终止还可以使用 std::thread::detach() 函数来实现,该函数可以让当前线程与创建的线程分离,使得两个线程可以独立运行,例如: ```cpp #include <thread> void worker_thread() { // ... } int main() { std::thread t(worker_thread); // 分离线程,使得两个线程可以独立运行 t.detach(); return 0; } ``` 需要注意的是,分离线程后,主线程不能再使用 join() 函数等待子线程执行完成,否则会导致程序崩溃。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值