Linux_learn/pthread/pthread.c 执行代码可以发现最后num值小于10000.
数据混乱原因如下图:
混乱原因:
- 操作了共享资源
- CPU调度问题
解决:
- 线程同步
线程同步思想
互斥锁:
特点:
- 让并行的线程,串行的访问数据。
- 同步效率变低
操作函数:
- 创建锁
pthread_mutex_t mutex; - 初始化
pthread_mutex_init(&mutex, NULL); - 加锁
pthread_mutex_lock(&mutex);
pthread_mutex_trylock(&mutex) //尝试加锁 - 解锁
pthread_mutex_unlock(pthread_mutex_t* mutex) - 销毁锁
pthread_mutex_destroy(pthread_mutex_t* mutex)
临界区:
加锁:pthread_mutex_lock
临界区 //被加锁跟解锁框住的区域称为临界区,临界区越小越好。
解锁:pthread_mutex_unlock
死锁:
一 . 自己锁自己
for(int i = 0; i < MAX; i++)
{
pthread_mutex_lock(&mutex); //mutex加锁
pthread_mutex_lock(&mutex); //阻塞
int count = num;
num ++;
pthread_mutex_unlock(&mutex);
}
解决办法:
切记!!加锁后一定要解锁。
二. 互锁
遇见互锁解决办法:
- 让线程按照一定的顺序访问共享资源
- 在访问其它锁的时候先把自己的锁解开
- 使用pthread_mutex_trylock 函数
注意事项:
有多少共享资源因该就有多少把锁。
读写锁
读写锁是一把锁
属性:
读锁 - 读内存操作
写锁 - 写内存操作
特性:
线程A加读锁成功,又来了三个线程,做读操作,可以加锁成功。
- 读共享
线程A加写锁成功,又来了三个线程,做读操作,三个线程阻塞。
- 写独享
线程A加读锁成功,又来了B线程加写锁阻塞,又来了C线程加读锁阻塞
- 读写不能同时进行
- 写的优先级高于读
操作函数:
-
创建锁
pthread_rwlock_t lock; -
初始化
pthread_rwlock_init(pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* restrict arrt); -
加读锁
pthread_rwlock_relock(pthread_rwlock_t* rwlock);
阻塞:前一次加了写锁 -
尝试加读锁
pthread_rwlock_tryrelock(pthread_rwlock_t* rwlock); -
加写锁
pthread_rwlock_wrlock(pthread_rwlock_t* rwlock);
阻塞:前一次加了写/读锁,还未解锁 -
尝试加写锁
pthread_rwlock_trywrelock(pthread_rwlock_t* rwlock); -
解锁
pthread_rwlock_unlock(pthread_rwlock_t* rwlock); -
销毁锁
pthread_rwlock_destroy(pthread_rwlock_t* rwlock)
条件变量:
作用:
就是在不满足条件的情况下可以阻塞线程。但不是锁
同步:
条件变量 + 互斥量 才能实现线程的同步。
操作函数:
创建一个条件变量
pthread_cond_t cond;
初始化一个条件变量
pthread_cond_init(pthread_cond_t* restrict cond, pthread_mutex_t* restrict mutex);
阻塞等待一个条件变量
pthread_cond_wait(pthread_cond_t* restrict cond, pthread_mutex_t* restrict mutex);
阻塞时会偷偷的把mutex解锁
解除阻塞时又会偷偷的给mutex加上锁
限时等待一个条件变量
pthread_cond_timedwait(pthread_cond_t* restrict cond, pthread_mutex_t* restrict mutex, const struct timespec* restrict abstime);
唤醒至少一个阻塞在条件变量上的线程
pthread_cond_signal(pthread_cond_t* cond);
唤醒全部阻塞在条件变量上的线程
pthread_cond_broadcast(pthread_cond_t* cond);
销毁一个条件变量
pthread_cond_destroy(pthread_cond_t* cond);
生产者消费者模型思路:
信号量(信号灯)
高级的互斥锁,允许多个线程同时访问共享资源。
操作函数:
头文件:
semaphore.h
创建一个信号量
sem_t sem;
初始化一个信号量
sem_init(sem_t* sem, int pshared, unsigned int value);
pshared:
0 - 线程同步
1 - 进程同步
value:设置最多可以有几个线程操作共享资源
加锁:
sem_wait(sem_t* sem);
这个函数相当于对sem_init的value做减减操作( value-- ), 如果value为5这个函数需要调用五次才会阻塞。(value=0 阻塞)
尝试加锁:
sem_trywait(sem_t* sem);
函数返回值为0代表成功。
加锁失败不阻塞,直接返回。
限时尝试加锁:
sem_timedwait(sem_t* sem, timeout);
//Todo
解锁:
sem_post(sem_t* sem);
对sem_init的value做 ++操作。
销毁信号:
sem_destroy(sem_t* sem);
生产者消费者思想: