(1)线程同步
1)线程同步:指一个线程发出某一个功能运行时,在运行还没有结束的时候,该调用不返回。同时其它线程为保证数据的一致性,不能调用该功能。
2)多个控制流共同操作一个共享资源的时候,都需要同步。
3)数据混乱的原因:1》资源共享 2》调度随机 3》线程间缺乏必要的同步机制。
前两点无法避免,只能从第三点开始优化。
(2)互斥量mutex
1)linux中提供一把互斥锁mutex(互斥量),每个线程都是提前对资源操作前都尝试先加锁,成功加锁才能操作,操作结束后解锁。
2)同一个时刻,只能有一个线程持有该锁。
3)当线程A多某个全局变量加锁访问时,B在访问时尝试加锁,失败后,B阻塞。C线程不加锁访问全局变量,可以访问,但是数据混乱,因此互斥锁又被成为“建议锁”(协同锁),没有强制限定。
(3)互斥量及相关函数:
pthread_mutex_t类型,一个结构体,使用时可看做整数。函数成功返回0,失败返回错误号。
1)pthread_mutex_intit:初始化一个互斥锁(互斥量) -->初值可看作1
int pthread_mutex_init(pthread_mutex_t*restrict mutex,const pthread_mutexattr_t*restrict attr);
参数1;传出参数,待初始化的互斥量。
参数2:看成互斥量属性,出入参数,通常传NULL,表示默认属性(线程间共享)
静态初始化: 使用宏初始化 pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
动态初始化:使用函数初始化。
2)pthread_mutex_destory:销毁一个互斥锁
int pthread_nutex_destory(pthread_mutex_t *mutex);
3)pthread_mutex_lock:加锁
尝试加锁,加锁不成功,则阻塞。
int pthread_nutex_lock(pthread_mutex_t *mutex);
4)pthread_mutex_unlock:解锁
唤醒阻塞所有线程。
int pthread_nutex_unlock(pthread_mutex_t *mutex);
5)pthread_mutex_trylock:尝试加锁
加锁失败后返回错误号,不阻塞。
int pthread_nutex_trylock(pthread_mutex_t *mutex);
(4)加锁解锁测试:不同线程实现不同的打印任务
结论:在访问共享资源时加锁,访问结束后解锁,锁的“粒度”越小越好
(5)死锁
1)同一个线程试图多同一个互斥量加锁两次。
2)线程1拥有A锁请求B锁;线程2拥有B锁请求A锁。