线程同步-互斥量

线程同步-互斥量

文章目录

学习目标:

掌握互斥锁函数
掌握读写锁操作函数


线程同步概念:

即当有一个线程在对内存进行操作时,其它线程都不可以对这个内存地址进行操作,直到该线程完成操作,其它线程才能对该内存地址进行操作,而其它线程又处于等待状态。为了防止数据混乱,产生与时间有关的错误。


互斥量:

互斥量: 用来同步同一个进程中的各个线程,如果一个互斥量存放在多个进程共享的某个内存区中,还可以通过互斥量来进行进程间的同步,是用来保护临界区(共享资源),以保证仍和时刻只有一个线程能访问共享的资源。所有进程【应该】在访问公共数据前先拿锁在访问。


使用互斥量步骤:

函数原型
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;//静态初始化读写锁

上一篇:用C++实现单例模式几种写法


下一篇:2021.7.16快乐实验