同一个进程中的多个线程共享所在进程的内存资源,当多个线程在同一时刻同时访问同一种共享资源时,需要相互协调,以避免出现数据的不一致和覆盖等问题,线程之间的协调和通信的就叫做线程的同步问题, 线程同步的思路: 让多个线程依次访问共享资源,而不是并行
互斥VS同步互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源
互斥量Mutex:本质上说就是一把锁,提供对资源的独占访问,所以Mutex主要的作用是用于互斥。互斥量使同时只能有一个进程访问数据,可以看做一种的0/1信号量
Mutex对象的值只有0和1。分别代表了Mutex的锁定状态和空闲状态:
锁定状态:当前对象被锁定,用户进程/线程如果试图Lock临界资源,则进入等待;
空闲状态:当前对象为空闲,用户进程/线程可以Lock临界资源,之后Mutex值减1变为0。
Mutex被创建时可以有初始值,表示Mutex被创建后,是锁定状态还是空闲状态。
在同一个线程中,为了防止死锁,系统不允许连续两次对Mutex加锁(系统一般会在第二次调用立刻返回)。也就是说,加锁和解锁这两个对应的操作,需要在同一个线程中完成。
互斥量模型定义互斥锁: pthread_t mutex
初始化锁: pthread_mutex_init()
加锁: pthread_mutex_lock()/pthread_mutex_trylock()
解锁: pthread_mutex_unlock()
销毁: pthread_mutex_destroy()
//成功返回0,失败返回error number #include <pthread.h> int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); int pthread_mutex_lock (pthread_mutex_t *mutex); int pthread_mutex_trylock (pthread_mutex_t *mutex); int pthread_mutex_unlock (pthread_mutex_t *mutex); int pthread_mutex_destroy (pthread_mutex_t *mutex); 死锁(deadlock)主要发生在有多个依赖锁存在时, 会在一个线程试图以与另一个线程相反顺序锁住互斥量时发生:
A试图按照AB的方向使用共享资源,B试图按照BA的方向使用共享资源,不巧的是,此时锁定A资源等待B资源被释放, 也在锁定B资源等待A资源被释放, 二者将要使用的资源都被对方锁着, 形成了死锁。
为避免死锁, 有几个不成文的基本原则:
对共享资源操作前一定要获得锁。
完成操作以后一定要释放锁。