线程同步的几种方式

目录

线程同步方式有互斥锁,条件变量,信号量,读写锁,CAS锁等方式

互斥锁

  • 互斥量 pthread_mutex_t
  • 在执行操作之前加锁,操作完之后解锁. 使用互斥量,来确保同一时刻只有一个线程访问某项共享资源。
  • A线程加锁了,B线程无法释放A线程加的锁,只能等A线程自己释放,锁释放后再竞争锁
cpp 复制代码
pthread_mutex_t lock;//创建锁
pthread_mutex_init();//初始化锁
pthread_mutex_lock();//加锁
pthread_mutex_unlock();//解锁
pthread_mutex_destroy();//销毁锁

条件变量

  • 条件变量可以同时唤醒一个或多个线程,信号量只能唤醒一个,唤醒多个线程的时候,通常涉及到资源竞争,往往配合互斥锁使用
  • 条件变量是线程的另一种同步机制,它和互斥量是一起使用的。互斥量的目的就是为了加锁,而条件变量的结合,使得线程能够以等待的状态来迎接特定的条件发生,而不需要频繁查询锁。
cpp 复制代码
pthread_cond_t cond; //创建条件变量
pthread_cond_init();//初始化条件变量
pthread_cond_wait();//线程进入阻塞,等待信号被唤醒
pthread_cond_timedwait();//线程进入阻塞,一定时间后被唤醒
pthread_cond_signal();//满足条件后一次通知一个
pthread_cond_broadcast();//满足条件后一次通知多个
pthread_cond_destroy(); //销毁条件变量

读写锁

  • 以读方式给数据加锁--------读锁。以写方式给数据加锁---------写锁。
    读共享,写独占。
    写锁优先级高。
  • 当线程A处于读的状态,线程B也可以读,但是不能写,当线程A处于写的状态,线程B则不能读,适用与少写多读的场景
cpp 复制代码
pthread_rwlock_t rwlock;//创建读写锁
pthread_rwlock_init();//初始化锁
pthread_rwlock_rdlock();//加读锁
pthread_rwlock_wrlock();//加写锁
pthread_rwlock_trywrlock();//try锁
pthread_rwlock_unlock();//解锁
pthread_rwlock_destroy();//销毁锁多的时候,提高访问效率

信号量

  • 信号量是一种特殊的变量,用来控制对临界资源的使用,在多个进程或线程都要访问临界资源的时候,就需要控制多个进行或线程对临界资源的使用。
  • 信号量机制通过p、v操作实现。p操作:原子减1,申请资源,当信号量为0时,p操作阻塞;v操作:原子加1,释放资源。
cpp 复制代码
  sem_t sem;
  int sem_init(sem_t *sem, int pshared, unsigned int value);
  //初始化
  //pshared传零用于线程间同步,传1用于进程和线程间同步
  //value也就是N
  int sem_wait(sem_t *sem);//加锁系信号量,信号量大于0,信号--操作,信号量等于0阻塞
  int sem_trywait(sem_t *sem);//try锁
  int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
 //限时尝试对信号进行加锁
  int sem_post(sem_t *sem);//解锁,将信号量++,同时唤醒阻塞在信号量上的线程
  int sem_destroy(sem_t *sem);//销毁信号量

CAS

  • CAS是基于乐观锁的线程同步方式
  • CAS算法的作用:解决多线程条件下使用锁造成性能损耗问题的算法,保证了原子性,这个原子操作是由CPU来完成的
    CAS的原理:CAS算法有三个操作数,通过内存中的值(V)、预期原始值(A)、修改后的新值。
    (1)如果内存中的值和预期原始值相等, 就将修改后的新值保存到内存中。
    (2)如果内存中的值和预期原始值不相等,说明共享数据已经被修改,放弃已经所做的操作,然后重新执行刚才的操作,直到重试成功。
cpp 复制代码
// 伪代码
template <class T>
bool CAS(T* addr, T expected, T target) 
{
   if (*addr == expected) 
   {
      *addr = target;
      return true;
   }
   return false;
}

-- 参考

https://www.cnblogs.com/Chlik/p/13556720.html
http://t.csdnimg.cn/GB6En
https://www.zhihu.com/question/485896579
https://zhuanlan.zhihu.com/p/400817892

相关推荐
别NULL11 分钟前
机试题——疯长的草
数据结构·c++·算法
dessler31 分钟前
Docker-run命令详细讲解
linux·运维·后端·docker
飞飞-躺着更舒服42 分钟前
【QT】实现电子飞行显示器(改进版)
开发语言·qt
武昌库里写JAVA1 小时前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计
PyAIGCMaster1 小时前
ubuntu装P104驱动
linux·运维·ubuntu
奈何不吃鱼1 小时前
【Linux】ubuntu依赖安装的各种问题汇总
linux·运维·服务器
icy、泡芙1 小时前
T527-----音频调试
linux·驱动开发·音视频
aherhuo1 小时前
kubevirt网络
linux·云原生·容器·kubernetes
CYBEREXP20081 小时前
MacOS M3源代码编译Qt6.8.1
c++·qt·macos
zzzhpzhpzzz1 小时前
Ubuntu如何查看硬件型号
linux·运维·ubuntu