【Linux 线程同步】互斥锁,信号量,条件变量,读写锁

互斥锁

API

int pthread_mutex_init(pthread_mutex_t *mutex,pthread_mutexattr_t*attr);
mutex 参数表示要初始化的互斥锁;attr 参数用于自定义新建互斥锁的属性,attr 的值为 NULL 时表示以默认属性创建互斥锁。
int pthread_mutex_lock(pthread_mutex_t *mutex);对互斥锁进行加锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);对互斥锁进行解锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);摧毁互斥锁

互斥锁的案例

5个线程同时对一个全局变量加1000次

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
int m_index =0;
pthread_mutex_t mutex;
void * fun(void *arg)
{
  for(int i=0;i<1000;++i)
  {
   pthread_mutex_lock(&mutex);
   printf("index =%d\n",++m_index);
   pthread_mutex_unlock(&mutex);
  }

}
int main()
{
 pthread_mutex_init(&mutex,NULL);
 pthread_t arid[5]={0};
 for(int i=0;i<5;++i)
 {
  pthread_create(&arid[i],NULL,fun,NULL);

 
 }
 for(int i=0;i<5;++i)
 {
   pthread_join(arid[i],NULL);
 
 }
 pthread_mutex_destroy(&mutex);
  exit(0);

}

执行结果
在这里插入图片描述

信号量

API

int sem_init(sem_t *sem, int pshared, unsigned int value);创建信号量
要创建的信号量
pshared 控制信号量的类型,值为 0 代表该信号量用于多线程间的同步,值如果大于 0 表示可以共享,用于多个相关进程间的同步
value为给该信号量的初始值
int sem_wait(sem_t*sem);对该信号量减1
int sem_post(sem_t*sem);对该信号量加1
int sem_destroy(sem_t *sem);摧毁该信号量

信号量的案例

当创建1个信号量且它的值为1时,可以实现和互斥锁一样的功能
下面为5个线程同时对一个全局变量加1000次

#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>
int g_index;
sem_t g_sem;
void * fun(void * arg)
{
    for(int i=0;i<1000;++i)
    {
        sem_wait(&g_sem);
        std::cout<<++g_index<<std::endl;
        sem_post(&g_sem);
    }
    return NULL;
}
int main()
{
    pthread_t pidArr[5];
    sem_init(&g_sem,0,1);
    for(int i=0;i<5;++i)
    {
        pthread_create(&pidArr[i],NULL,fun,NULL);
    }
    for(int i=0;i<5;++i)
    {
        pthread_join(pidArr[i],NULL);
    }
    sem_destroy(&g_sem);
    return 0;
}

在这里插入图片描述

条件变量

API

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t*attr);
 cond: 用于指明要初始化的条件变量;
 attr :用于自定义条件变量的属性,通常我们将它赋值为 NULL,表示以系统默认的属性完成初始化操作。
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
cond :表示已初始化好的条件变量;
mutex:表示与条件变量配合使用的互斥锁;
int pthread_cond_signal(pthread_cond_t *cond);唤醒单个线程
cond :表示初始化好的条件变量
int pthread_cond_broadcast(pthread_cond_t *cond);唤醒所有等待的线程
cond :表示初始化好的条件变量
int pthread_cond_destroy(pthread_cond_t*cond);销毁条件变量
cond :表示初始化好的条件变量

案例

获得键盘输入,并通知一个线程打印

#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<cstring>
pthread_mutex_t g_mutex;
pthread_cond_t g_cond;
void * fun1(void * arg)
{
  char * s = (char * )arg;
  while(1)
  {
     pthread_mutex_lock(&g_mutex);
     pthread_cond_wait(&g_cond,&g_mutex);
     pthread_mutex_unlock(&g_mutex); //把释放锁要放到if前面,要不然就会造成死锁
      if(strncmp(s,"end",3) ==0)
     {
        break;
     }
     std::cout<<"fun1"<<s<<std::endl;
  }

  return NULL;
}
void * fun2(void * arg)
{
  char * s = (char * )arg;
  while(1)
  {
     pthread_mutex_lock(&g_mutex);
     pthread_cond_wait(&g_cond,&g_mutex);
     pthread_mutex_unlock(&g_mutex);
         if(strncmp(s,"end",3) ==0)
     {
        break;
     }
     std::cout<<"fun2"<<s<<std::endl;
  }

    return NULL;
}
int main()
{
   pthread_cond_init(&g_cond,NULL);
   pthread_mutex_init(&g_mutex,NULL);
   char buff[128]={0};
   pthread_t pidArr[2]={0};
   pthread_create(&pidArr[0],NULL,fun1,buff);
   pthread_create(&pidArr[1],NULL,fun2,buff);

   while(1)
   {
    std::cout<<"please input"<<std::endl;
    fgets(buff,127,stdin);
    if(strncmp(buff,"end",3) ==0)
    {
        pthread_cond_broadcast(&g_cond);
        break;
    }else
    {
      pthread_cond_signal(&g_cond);
     
    }
   }
   
   pthread_join(pidArr[0],NULL);
   pthread_join(pidArr[1],NULL);

   pthread_cond_destroy(&g_cond);
   pthread_mutex_destroy(&g_mutex);
    exit(0);
}

运行结果
在这里插入图片描述
在这里插入图片描述

读写锁

写的时候不能读,可以多个线程同时读,但是只能有一个线程一个时刻写

API

int pthread_rwlock_init(pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr); 初始化锁
rwlock:要初始化的锁
attr:表示读写锁属性,通常传NULL,表示使用默认属性;
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);以读方式请求锁
rwlock:要请求的锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);以写的方式请求锁
rwlock:要请求的锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);解锁
rwlock:要解锁的锁
 int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);销毁锁
 rwlock:要销毁的锁

案例

用两个线程模仿读,一个线程模仿写

#include<stdio.h>
#include<iostream>
#include<unistd.h>
#include<string.h>
#include<pthread.h>
#include<semaphore.h>
pthread_rwlock_t g_rwlock;
void * fun1(void * arg)
{
    for(int i=0;i<5;++i)
    {
        pthread_rwlock_rdlock(&g_rwlock);
        std::cout<<"A read start.."<<std::endl;
        sleep(rand()%3);
        std::cout<<"A read end.."<<std::endl;
        pthread_rwlock_unlock(&g_rwlock);
    }
    return NULL;

}
void * fun2(void * arg)
{

    for(int i=0;i<5;++i)
    {
      pthread_rwlock_rdlock(&g_rwlock);
      std::cout<<"B read start.."<<std::endl;
      sleep(rand()%3);
      std::cout<<"B read end"<<std::endl;
      pthread_rwlock_unlock(&g_rwlock);
    }
    return NULL;
}
void * fun3(void * arg)
{
  for(int i=0;i<5;++i)
  {
    pthread_rwlock_wrlock(&g_rwlock);
     std::cout<<"write start"<<std::endl;
    sleep(rand()%3);
    std::cout<<"write end"<<std::endl;
    pthread_rwlock_unlock(&g_rwlock);
  }
  return NULL;
}
int main()
{
 pthread_rwlock_init(&g_rwlock,NULL);
 pthread_t id1,id2,id3;

 pthread_create(&id1,NULL,fun1,NULL);
 pthread_create(&id2,NULL,fun2,NULL);
 pthread_create(&id3,NULL,fun3,NULL);

 pthread_join(id1,NULL);
 pthread_join(id2,NULL);
 pthread_join(id3,NULL);

 pthread_rwlock_destroy(&g_rwlock);
 exit(0);
}

运行结果
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值