互斥锁 读写锁 条件变量 信号量

1. 线程同步

1.1为什么要做线程同步

  当程序有多个线程访问同一资源时,各个线程的操作各不相同,一部分线程在读该资源,一部分线程在写该资源,就会发生冲突,可能一个线程正在读该资源时候该资源的内容被其他线程写操作改变了,所以需要进行线程同步。

1.2线程同步的四种方式

四种方式:互斥锁,读写锁,条件变量,信号量

2.互斥锁

2.1互斥锁定义

#include<pthread.h>
pthread_mutex_t mutex;

2.2互斥锁初始化

int pthread_mutex_init(&pthread_mutex_t *restrict mutex,const pthread_mutexattr_t  *restrict attr);
//mutex为定义的互斥锁,attr为指向线程属性的结构体,一般采用默认属性NULL

2.3互斥锁释放

int pthread_mutex_destroy(pthread_mutex_t *mutex);

2.4加锁解锁

int pthread_mutex_lock(pthread_mutex_t *mutex);
/*加锁函数,资源若已被别的线程加锁则阻塞,
等待锁被释放再加锁,参数mutex为互斥锁的地址*/
int pthread_mutex_trylock(pthread_mutex_t *mutex);
//尝试加锁函数,如果已经该资源已经被其他线程上锁,
//则不会上锁,不会阻塞直接返回错误号
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//解锁函数,参数mutex为互斥锁的地址

3.读写锁

  1.读写锁提供更为精确的操作,是可以进行读和写两种功能的锁。
  2.互斥锁多个线程不管是进行读操作还是写操作都是串行的,都需要抢同一把锁来访问共同资源
  3.读写锁中读操作是并行的,如果所有线程都对同一资源进行读操作则都可以一起进行;写操作是串行的,必须通过读写锁进行上写锁才能优先进行写操作,写操作的优先级比读操作高

3.1读写锁定义

#include<pthread.h>
pthread_rwlcok_t rwlock;

3.2读写锁初始化

int pthread_rwlock_init(pthread_rwlock_t*restrict rwlock,pthread_rwlockattr_t *restrict attr);
//rwlock是定义的读写锁,attr是读写锁结构体属性,
//一般使用默认属性NULL

3.3读写锁释放

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

3.4加读锁

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
/*调用该函数访问资源如果有其他线程对该资源上了写锁则本线程阻塞等待,上读锁则不影响*/
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
//尝试加锁,如果已经加了写锁则直接返回错误号

3.5加写锁

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

3.6解锁

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

4.条件变量

条件变量跟互斥锁不同的是
多个线程访问临界区,如果一个线程加了互斥锁,其他线程就会阻塞,当这个线程解锁时,只有一个线程能抢到这把锁,其他线程还是只能阻塞等待下一次解锁
条件变量当满足一定条件就会阻塞该线程,不满足时多个线程讲同时访问临界区会造成数据的混乱

4.1条件变量定义

#include<pthread.h>
pthread_cond_t cond;

4.2条件变量初始化

int pthred_cond_init(pthread_cond_t *restrict cond,pthread_condattr_t *restrict attr);
//cond是已经定义的条件变量,attr是指向条件变量的结构体,一般使用默认属性

4.3条件变量等待

调用该函数的线程会被阻塞,如果该线程已经对互斥锁上锁,那么会先解锁,避免产生死锁现象
当线程解除阻塞时,会把该线程的互斥锁再次加上,继续向下访问临界区

int pthread_cond_wait(pthread_cond_t*restrict cond,pthread_mutex_t *restrict mutex);
//参数mutex是互斥锁

4.4条件变量唤醒

int pthread_cond_signal(pthread_cond_t *cond)
//唤醒阻塞在该条件变量上的线程,至少唤醒一个被阻塞的线程
int pthread_cond_broadcast(pthread_cond_t *cond);
//唤醒阻塞在该条件变量上的线程,解除全部阻塞的线程

5.信号量

信号量适用于多线程多任务同步的,一个线程完成了一个动作就通过信号量告诉别的线程,别的线程再进行某些动作。比如线程2需要等待线程1完成某一任务自己才能进行下一操作。
信号量主要是阻塞线程,并不能保证线程安全,如果要保证线程安全,需要配合互斥锁一起使用。

5.1 信号量定义

#include<semaphore.h>
sem_t sem;

5.2信号量初始化

int sem_init(sem_t *sem,int pshared,unsigned int value);
/*sem信号量变量地址,pshared:0 线程同步 非零 进程同步
value 初始化信号量拥有的资源数,如果资源数为零,则线程就会被阻塞了*/
int sem_destroy(sem_t*sem);
//信号量释放函数,sem为信号量地址

5.3信号量等待

int sem_wait(sem_t*sem);
/*当线程调用该函数时,资源数>0时线程不会阻塞,并且资源数-1,当资源数等于0时,资源被耗尽,线程就被阻塞了。*/
int sem_trywait(sem_t *sem);
//与上面不同的是,当资源数减为零时,不会阻塞会直接返回错误号。

5.4信号量资源+1

int sem_post(sem_t* sem);
/*该函数会将sem中的资源数+1,如果有线程调用sem_wait,sem_trywait等函数
因为资源数减为0了而阻塞,此时这些线程会解除阻塞,继续向下运行。*/

5.5信号量资源数获取

int sem_getvalue(sem_t *sem,int *sval);
//通过这个函数可以查看sem中现有的资源数,通过第二个参数传出
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值