1.同步和互斥

概念

互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问

2.互斥问题的解决方法:

2.1互斥锁机制

互斥锁是用一种简单的加锁方法来控制对共享资源的访问,互斥锁有两种状态,上锁和解锁,可以把互斥锁看作成某种意义上的全局变量。在同一时刻只能有一个线程掌握这个互斥锁,拥有上锁状态的线程能够对共享资源按照顺序进行操作。若其他线程希望上锁一个已经被上锁的互斥锁,则该线程会被挂起,直到互斥锁被上锁的线程释放(解锁)。
image.png

互斥锁基本操作(独占)

1)申请初始化互斥锁:
静态化初始:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
动态化初始:
pthread_mutex_t mutex;
pthread_mutex_init (&mutex,NULL);//主线程
image.png
2)申请互斥锁(上锁)
int pthread_mutex_lock(&mutex ); //共享资源访问之前
image.png
3)释放互斥锁(解锁)
int pthread_mutex_unlock(&mutex );//共享资源访问结束
image.png
4)销毁互斥锁(释放锁)
int pthread_mutex_destroy(&mutex);//主线程
image.png

  1. ** 一般要加上线程清理函数,防止产生资源死锁状态,造成其他线程阻塞;清理函数中是释放锁资源** int pthread_mutex_destroy(&mutex);

2.2读写锁机制

读写锁(共享-独占锁):可以根据具体的资源访问方式,决定对共享资源是独占访问还是共享访问;
使用场景:多用于读操作频率高于写操作频率;
image.pngimage.png

读写锁:三个状态:
读上锁
写上锁
解锁
image.png

读写锁基本操作

1)申请初始化读写锁:
静态初始化:pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER

动态初始化:
pthread_rwlock_t rwlock;
pthread_rwlock_init (&rwlock,NULL);//主线程
image.png
2)读上锁:
int pthread_rwlock_rdlock(&rwlock ); //共享资源访问之前
image.png
3)写上锁:
int pthread_rwlock_wrlock(&rwlock ); //共享资源访问之前
4)释放锁:
int pthread_rwlock_unlock (&rwlock );
image.png
5)销毁锁:
int pthread_rwlock_destroy(&rwlock);
image.png

2.3条件变量机制

主要用于对共享资源进行有条件的访问;
image.png
条件变量主要是用来阻塞一个线程,条件变量允许线程以无竞争的方式等待条件的发生;
注意:条件变量必须搭配互斥锁一起使用,原因在于条件的检测是必须在互斥锁的保护下进行;
条件变量的使用:
1.由主线程申请初始化条件变量;
2.子线程如果对共享资源由条件访问,判断条件,条件并不成立,利用条件变量阻塞线程;
3.子线程如果对共享资源的访问,同时修改条件,对条件变量进行通知唤醒被条件变量阻塞的线程;
4.由主线程回收条件变量;

条件变量的操作

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/21767570/1626079963553-75fc747e-cb29-4e8a-baef-4855dfa6c56f.png#align=left&display=inline&height=291&margin=%5Bobject%20Object%5D&name=image.png&originHeight=517&originWidth=800&size=236016&status=done&style=none&width=451)
  2. 1) 申请初始化条件变量: <br /> 静态初始化:pthread_cond_t rwlock = PTHREAD_COND_INITIALIZER;<br /> 动态初始化:<br /> pthread_cond_t cond;<br /> pthread_cond_init(&cond,NULL); //主线程<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/21767570/1626142710708-b6f545c2-96b3-4106-8478-3891b08ba114.png#align=left&display=inline&height=368&margin=%5Bobject%20Object%5D&name=image.png&originHeight=380&originWidth=617&size=286265&status=done&style=none&width=598)<br /> 2) 等待条件变量: <br />pthread_cond_wait(&cond,&mutex); //读线程共享资源访问前<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/21767570/1626142730028-ba4da7ce-0c04-4816-bef3-aa7020e3613e.png#align=left&display=inline&height=261&margin=%5Bobject%20Object%5D&name=image.png&originHeight=307&originWidth=710&size=223908&status=done&style=none&width=603)<br /> 3) 通知条件变量: <br />pthread_cond_signal(&cond); //写线程共享资源访问前<br /> pthread_cond_broadcast(&cond);<br /> ![image.png](https://cdn.nlark.com/yuque/0/2021/png/21767570/1626141560247-dc305285-8757-49f5-801a-7257d4d23136.png#align=left&display=inline&height=367&margin=%5Bobject%20Object%5D&name=image.png&originHeight=434&originWidth=717&size=297857&status=done&style=none&width=606)<br /> <br /> 5) 释放条件变量: pthread_cond_destroy(&cond); //主线程<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/21767570/1626142805909-91701d50-7711-44e7-adc3-5457c6cb5aba.png#align=left&display=inline&height=314&margin=%5Bobject%20Object%5D&name=image.png&originHeight=332&originWidth=645&size=254752&status=done&style=none&width=611)

相关编程接口函数