线程同步实现方式

1. 条件变量(通互斥锁一起使用,互斥锁用来保护等待队列的)

2. 线程信号量

 

条件变量:

  条件变量的内部是一个等待队列,这个队列中放置阻塞的线程,线程在这个队列中等待通知。

  因为这个等待队列也时一个共享资源,所以也要用一把互斥锁来保护,即对等待队列上锁。

  队列中的线程等特定的条件发生,当条件不满足时,线程先进入阻塞状态,等待条件的发生。一旦其他的某个线程改变了条件,就可唤醒一个或多个阻塞的线程。

数据类型:pthread_cond_t

 

条件变量的创建和销毁:

  

 

参数:

  cond:条件变量

  attr:条件变量属性,和互斥锁属性类似

 

条件变量的等待:

  将线程放入等待队列中

  

 

 参数:

  cond:条件变量

  mutex:互斥锁

  互斥锁是对条件变量cond保护

 

条件变量的通知和唤醒:

  

 

 参数:

  cond:条件变量

当条件满足时,线程通知等待的线程

signal是通知单个线程;broadcast是通知所有线程

 

pthread_cond_wait(cond,mutex)函数内部的流程:

  

 

 

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


typedef struct
{
    int res;
    int is_wait;
    
    pthread_cond_t cond;//条件变量也要和共享资源绑定
    pthread_mutex_t mutex;//保护条件变量
}ResArg;

void *cal_fn(void *arg)
{
    ResArg *result = (ResArg *)arg;
    int i = 0;
    int sum = 0;
    for(i = 0;i <101; i++){
        sum +=i;
    }
    result->res = sum;
    
    pthread_mutex_lock(&result->mutex);
    while(result->is_wait == 0){//判断是否调用了wait函数
        pthread_mutex_unlock(&result->mutex);
        usleep(100);
        pthread_mutex_lock(&result->mutex);//这里阻塞是保证wait函数先调用
    }   
  //pthread_mutex_lock(&result->mutex); 加锁在while外不行 pthread_mutex_unlock(
&result->mutex); pthread_cond_broadcast(&result->cond);//每次都要先保证wait函数先执行,然后在调用broadcast (void *)0; }
//如果pthread_mutex_lock(&result->mutex);放在while外,会出现问题,有几率出现如下顺序:
//在cal_fn函数中先加锁,然后判断is_wait=0就会解锁并阻塞,然后get_fn得到的时间片只够调用加锁,这时is_wait还是为0;
//然后cal_fn再次获得时间片,进入循环会将get_fn函数中加的锁解掉(这是就是无锁的状态),然后cal_fn再进入延时阻塞,
//这时get_fn又获得时间片,将is_wait置为1,然后将获得的时间片用完,这时的is_wait为1了。
//cal_fn阻塞完后再次判断is_wait不等于0了,退出循环,然后再加锁、解锁,再调用broadcast(这样broadcast就在wait之前了,就不行)

void *get_fn(void *arg) { ResArg *result = (ResArg *)arg; pthread_mutex_lock(&result->mutex); result->is_wait = 1;//将这个flag和wait函数绑定,1:表示调用了wait函数;0:表示没调用wait函数 pthread_cond_wait(&result->cond,&result->mutex); pthread_mutex_unlock(&result->mutex);//unlock在wait函数后,因为wait函数内部有上了互斥锁 printf("reslt = %d\n",result->res); (void *)0; } int main(void) { int err; pthread_t cal,get; ResArg r; r.is_wait = 0; pthread_cond_init(&r.cond,NULL); pthread_mutex_init(&r.mutex,NULL); if(pthread_create(&cal,NULL,cal_fn,(void *)&r) != 0){ printf("cal pthread creat fail\n"); } if(pthread_create(&get,NULL,get_fn,(void *)&r) != 0){ printf("get pthread creat fail\n"); } pthread_join(cal,NULL); pthread_join(get,NULL); pthread_cond_destroy(&r.cond); pthread_mutex_destroy(&r.mutex); return 0; }

 

posted @ 2023-02-26 21:10  踏浪而来的人  阅读(13)  评论(0编辑  收藏  举报