**主要内容:
(1)互斥量及如何使用
(2)什么是死锁,如何解决
(3)什么是读写锁,如何使用**
(4)条件变量实现的生产消费者模型
(5)信号量实现的生产消费者模型
**线程同步**
协调步骤,顺序执行。解决同步的问题:加锁!
数据混乱的原因:
- 资源共享(独享资源则不会);
- 随机调度(意味着数据访问会出现竞争);
- 线程间缺乏必要的同步机制。(解决该点最为可行,因此需要用到互斥量)
**1.mutex互斥量**
两个线程访问同一块共享资源,如果不协调顺序,容易造成数据混乱。解决方法:加锁--mutex
- pthread_mutex_init 初始化
- pthread_mutex_destroy 摧毁
- pthread_mutex_lock 加锁
- pthread_mutex_unlock(pthread_mutex_t *mutex) 解锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
- restrict 约束该块内存区域对应的数据,只能通过后面的变量进行访问和修改
- mutex 互斥量--锁
- attr 互斥量的属性,可不考虑,传NULL
互斥量的使用步骤:
- 初始化
- 加锁
- 执行逻辑--操作共享数据
- 解锁
注意事项:加锁需要最小粒度,不要一直占用临界区。
尝试加锁:
int pthread_mutex_trylock(pthread_mutex_t *mutex);
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<string.h>
pthread_mutex_t mutex;
void *thr(void *arg)
{
while (1)
{
pthread_mutex_lock(&mutex);
printf("hello world\n");
sleep(30);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main()
{
pthread_mutex_init(&mutex,NULL);
pthread_t tid;
pthread_create(&tid,NULL,thr,NULL);
sleep(1);
while (1)
{
int ret = pthread_mutex_trylock(&mutex); //尝试加锁,如果加不上打印错误。因为锁被子线程占用,所以加不成功。
if(ret > 0)
{
printf("ret = %d, srrmsg:%s\n",ret,strerror(ret));
}
sleep(1);
}
return 0;
}
输出:
~$ gcc mutex_trylock.c -lpthread
~$ ./a.out
hello world
ret = 16, srrmsg:Device or resource busy
ret = 16, srrmsg:Device or resource busy
ret = 16, srrmsg:Device or resource busy
ret = 16, srrmsg:Device or resource busy
ret = 16, srrmsg:Device or resource busy
**2.死锁**
(1)锁了又锁,自己加了一次锁成功,又加了一次;
(2)交叉锁。解决办法:每个线程申请锁的顺序要一致;如果申请到一把锁,申请另一把锁的时候申请失败,应该释放已经掌握的。