互斥量:
当多个线程共享相同的内存时,需要每一个线程看到相同的视图。当一个线程修改变量时,而其他线程也可以读取或者修改这个变量,就需要对这些线程同步,确保他们不会访问到无效的变量
在变量修改时间多于一个存储器访问周期的处理器结构中,当存储器的读和写这两个周期交叉时,这种潜在的不一致性就会出现。当然这与处理器相关,但是在可移植的程序中并不能对处理器做出任何假设
为了让线程访问数据不产生冲突,这要就需要对变量加锁,使得同一时刻只有一个线程可以访问变量。互斥量本质就是锁,访问共享资源前对互斥量加锁,访问完成后解锁
当互斥量加锁以后,其他所有需要访问该互斥量的线程都将阻塞
当互斥量解锁以后,所有因为这个互斥量阻塞的线程都将变为就绪态,第一个获得cpu的线程会获得互斥量,变为运行态,而其他线程会继续变为阻塞,在这种方式下访问互斥量每次只有一个线程能向前执行
互斥量用pthread_mutex_t类型的数据表示,在使用之前需要对互斥量初始化
1、如果是动态分配的互斥量,可以调用pthread_mutex_init()函数初始化
2、如果是静态分配的互斥量,还可以把它置为常量PTHREAD_MUTEX_INITIALIZER
3、动态分配的互斥量在释放内存之前需要调用pthread_mutex_destroy()
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
加锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
成功返回0,失败返回错误码。如果互斥量已经被锁住,那么会导致该线程阻塞
int pthread_mutex_trylock(pthread_mutex_t *mutex);
成功返回0,失败返回错误码。如果互斥量已经被锁住,不会导致线程阻塞
解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
成功返回0,失败返回错误码。如果一个互斥量没有被锁住,那么解锁就会出错
死锁:线程一直在等待锁,而锁却无法解开
如果一个线程对已经占有的互斥量继续加锁,那么他就会陷入死锁状态。
lock mutex--------lock mutex--------阻塞
解除阻塞状态的条件:mutex unlock
mutex unlock的条件: 解除阻塞态
程序中使用多个互斥量时,如果一个线程一直占有互斥量A,并且试图加锁互斥量B,但是拥有互斥量B的线程却要加锁互斥量A,这时就会出现死锁
线程1: lock A成功
线程2 : lock B成功
线程1: lock B失败, 阻塞
线程2: lock A失败, 阻塞
线程1解除阻塞的条件:线程2将B解锁
线程2解除阻塞的条件:线程1将A解锁
如何去避免
你可以小心的控制互斥量加锁的顺序来避免死锁,例如所有的线程都在加锁B之前先加锁A,那么这两个互斥量就不会产生死锁了