Linux 线程同步

1. 线程同步:

当多个控制线程共享相同的内存时,需要确保每个线程看到一致的数据视图。当某个线程可以修改变量,而其他线程也可以读取或者修改这个变量的时候,就需要对这些线程进行同步,以确保他们在访问变量的存储内容的时候不会访问到无效的数值;

当一个线程修改变量时,其他线程在读取这个变量的值的时候可能看到不一致的数据,在变量修改时间多余一个存储器周期的处理器结构中,当存储器读与存储器写这两个周期交叉时,这种潜在的不一致性就会出现些;

 

2. 互斥量:

从本质上来说互斥量是一把锁,对互斥量进行加锁以后,任何其他视图再次对互斥量加锁的线程将会阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为运行状态的线程可以对互斥量加锁,其他线程将会看到互斥锁依然被锁住,只能回去再次等它重新变为可用,这种方式下,只有一个线程可以向前执行;

#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t *restrict mutex, 
const pthread_mutexattr_t *restrict attr); //默认属性可以设置为NULL int pthread_mutex_destroy(pthread_mutex_t *mutex); ret-成功返回0 失败返回错误编号
#include <pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex); //如果不希望阻塞,可以使用trylock尝试加锁,锁住返回0,或者返回EBUSY

int pthread_mutex_unlock(pthread_mutext_t *mutex);

ret-成功返回0 失败返回错误编号

产生死锁:

(1) 如果线程视图对同一个互斥量加锁两次,那么它自身就会陷入死锁状态;

(2) 程序中使用多个互斥量,如果允许一个线程一直占有第一个互斥量,并且在视图锁住第二个互斥量时处于阻塞状态,但是拥有第二个互斥量的线程也在视图锁住第一个互斥量,这样就会发生死锁;

避免死锁:

(1) 可以通过小心的控制互斥量加锁的顺序来避免死锁的发生。

(2) 如果不能获取锁,可以先释放占有的锁,过一段时间再试。

 

3. 读写锁:

读写锁与互斥量类似,不过允许更高的并行性。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁;

读写锁非常适合对数据结构读次数远大于写的情况。

#include <pthread.h>

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
                const pthread_rwlockattr_t *restrict attr); //默认属性传空

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

ret-成功返回0 失败返回错误编号 
#include <pthread.h>

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

ret-成功返回0 失败返回错误编号
#include <pthread.h>

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

ret-成功返回0 失败返回错误编码EBUSY

 

4. 条件变量:

条件变量与互斥量一起使用,允许线程以无竞争方式等待特定的条件发生。条件本身是由互斥量保护的,线程改变条件状态前必须先锁住互斥量,其他线程在获得互斥量之前不会觉察到这种改变,因为必须锁定互斥量以后才能计算条件。

#include <pthread.h>

int pthread_cond_init(pthread_cond_t *restrict cond,
                       pthread_condattr_t *restrict attr);

int ptherad_cond_destroy(pthread_cond_t *cond);

ret-成功返回0 失败返回错误编号

 

#include <pthread.h>

int pthread_cond_wait(pthread_cond_t *restrict cond, 
                  pthread_mutext_t *restrict mutex);

int pthread_cond_timewait(pthread_cond_t *restrict cond,
                 pthread_mutex_t *restrict mutex,
                 const struct timespec *restrict timeout);

ret-成功返回0 失败返回错误编号

传递给xxxwait的互斥量对条件进行保护,调用者把锁住的互斥量传递给函数。函数把调用线程放到等到条件的线程列表上,然后对互斥量解锁,这两个操作是原子的。这样就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作直接的时间通道,这样线程就不会错误条件的任何变化。xxxwait返回时,互斥量再次被锁住;

#include <pthread.h>

int pthead_cond_signal(pthread_cond_t *cond); //通知某个进程,也可以通知不止一个线程

int pthread_cond_broadcast(pthread_cond_t *cond); //通知所有线程

ret-成功返回0 失败返回错误编号

注意要在条件变量改变之后发生信号;

posted @ 2016-04-01 15:03  AlexAlex  阅读(337)  评论(0编辑  收藏  举报