线程同步-互斥量
文章目录
学习目标:
掌握互斥锁函数
掌握读写锁操作函数
线程同步概念:
即当有一个线程在对内存进行操作时,其它线程都不可以对这个内存地址进行操作,直到该线程完成操作,其它线程才能对该内存地址进行操作,而其它线程又处于等待状态。为了防止数据混乱,产生与时间有关的错误。
互斥量:
互斥量: 用来同步同一个进程中的各个线程,如果一个互斥量存放在多个进程共享的某个内存区中,还可以通过互斥量来进行进程间的同步,是用来保护临界区(共享资源),以保证仍和时刻只有一个线程能访问共享的资源。所有进程【应该】在访问公共数据前先拿锁在访问。
使用互斥量步骤:
函数原型int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict mutexattr);//初始化互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);//销毁锁
int pthread_mutex_lock(pthread_mutex_t *mutex);//加锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);//尝试加锁
参数mutex:传出参数
mutexattr:互斥锁属性
- PTHREAD_MUTEX_TIMED_NP:普通锁,当线程加锁以后,其余请求的锁将形成一个等待队列,在解锁后按优先级获得锁。
- PTHREAD_MUTEX_RECURSIVE_NP:检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同,保证不允许多次加锁时不会出现最简单情况下的死锁。
- PTHREAD_MUTEX_ADAPTIVE_NP:适应锁,如动作最简单的锁类型,仅等待解锁后重新竞争。
返回值成功:0
失败:errno
pthread_mutex_init 总是返回0
restrict 关键字: 用来限定指针变量,被该关键字限定的指针变量所指向的内存操作,必须由本指针完成。
使用互斥量步骤:
pthread_mutex_t lock;//创建锁
pthread_mutex_init(&lock,NULL);//初始化
pthread_mutex_lock(&lock);//加锁
访问共享数据
pthread_mutex_unlock(&lock);//解锁
pthread_mutex_destroy(&lock);//销毁锁
注意事项:
- 尽量保证锁的粒度越小越好。(访问共享数据时加锁,访问结束【立即】解锁)
- 互斥锁,本质是结构体。
- 加锁:++操作,阻塞线程。
- 解锁:–操作,唤醒阻塞在锁上的线程
- try锁,尝试加锁,成功–,失败返回,同时设置错误号EBUSY。
读写锁:
读写锁: 锁只有一把,以读方式给数据加锁(读锁),以写的方式给数据加锁(写锁)。(写独占,读共享。写锁的优先级高于读锁)相较于互斥量而言,当读线程较多时,能够提高访问效率。
函数原型
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);//初始化读写锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//销毁锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//加读锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//加写锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解锁
int pthread_rwlock_trydlock(pthread_rwlock_t *rwlock);//尝试加读锁
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);//尝试加写锁
参数rwlock:传出参数
attr:读写锁属性,传NULL表示使用默认属性
返回值成功:0
失败:errno
restrict 关键字: 用来限定指针变量,被该关键字限定的指针变量所指向的内存操作,必须由本指针完成。
使用互斥量步骤:
pthread_mutex_t mutex;//创建锁
pthread_mutex_init(&mutex,NULL);//初始化
pthread_mutex_lock(&mutex);//加锁
访问共享数据
pthread_mutex_unlock(&mutex);//解锁
pthread_mutex_destroy(&mutex);//销毁锁
注意事项:
- 尽量保证锁的粒度越小越好。(访问共享数据时加锁,访问结束【立即】解锁)
- 互斥锁,本质是结构体。
- 加锁:++操作,阻塞线程。
- 解锁:–操作,唤醒阻塞在锁上的线程
- try锁,尝试加锁,成功–,失败返回,同时设置错误号EBUSY。
补充:
死锁: 使用锁不恰当导致的现象
- 对一个锁反复lock
- 两个线程,各自持有一把锁,请求另一把。
静态初始化读写锁和互斥量:
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;//静态初始化读写锁