开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情
线程同步
下面的函数都是成功返回0,失败返回错误号。
1. mutext
-
初始化
#include <pthread.h> int pthread_mutex_destroy(pthread_mutex_t *mutex); int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;互斥量初始化后是1。
-
lock/unlock#include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex); // 堵塞 int pthread_mutex_trylock(pthread_mutex_t *mutex); // 不堵塞 int pthread_mutex_unlock(pthread_mutex_t *mutex);注意这是锁是为了保护共享数据区域,应该使得锁的粒度越小越好。 比如:
while(1) { pthread_mutex_lock(&mutex); printf("h "); // 1 sleep(rand() % 3); printf("w.\n"); // 2 pthread_mutex_unlock(&mutex); sleep(rand() % 3); }上面的锁是为了保护
stdout。unlock应该放在第二个print的位置,而不是放在最后一个sleep的后面。 -
死锁
-
同一个线程试图对同一个互斥量加锁两次,即两次调用
pthread_mutex_lock,而中间没有调用pthread_mutex_unlock。 -
线程1拥有A锁,请求B锁,线程2拥有B锁,请求A锁
pthread_mutex_trylock:当拿不到锁时,就会放弃所有的锁,就不会有死锁。
-
2. 读写锁
-
写独占,读共享,写锁优先级更高。相比较互斥量锁,效率更高,因为读时可以共享。
-
函数
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
3. 条件变量
-
条件变量不是锁,但它可以造成线程堵塞。通常和
mutex配合使用,给多线程提供一个会和的场所。 -
函数
#include <pthread.h> int pthread_cond_destroy(pthread_cond_t *cond); int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime); int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); int pthread_cond_broadcast(pthread_cond_t *cond); int pthread_cond_signal(pthread_cond_t *cond);-
pthread_cond_wait:堵塞等待一个条件变量。- 堵塞等待条件变量
cond满足 - 释放已掌握的互斥锁,相当于
pthread_mutex_unlock(&mutex)。这两步是一个原子操作。 - 当被唤醒,
pthread_cond_wait函数返回时,解除堵塞并且重新申请获取互斥锁。
- 堵塞等待条件变量
-
pthread_cond_broadcast/pthread_cond_signal:唤醒堵塞中的pthread_cond_wait。pthread_cond_broadcast:唤醒所有堵塞的条件量pthread_cond_signal: 至少唤醒一个条件量
-
pthread_cond_timedwait:-
绝对时间的获取:
time_t cur = time(NULL); // 获取当前的时间 timespec t; t.tv_sec = cur + secons; // 在当前时间的基础上向后偏移才能获取绝对时间
-
-
-
生产者与消费者设计模式
-
条件量的优点: 相较于mutex可以减少竞争。
如果直接使用mutex,除了生产者和消费者之间要竞争互斥量之外,消费者之间也需要竞争互斥量,但是如果链表中没有数据,消费者之间的竞争是没有意义的。通过条件变量的机制,只有在生产者完成生产之后,消费者之间才会开始竞争,提高了效率。