首页 > 其他分享 >线程同步精要

线程同步精要

时间:2023-09-01 19:57:10浏览次数:34  
标签:同步 变量 lock 加锁 线程 mutex 精要

  • 并发编程有两种基本模型:message passing & shared memory。
  • 线程同步的四项原则:
  1. 首要原则是最低限度的共享对象,减少需要同步的场合,一个对象能不暴露给别的线程就不要暴露,如果要暴露,优先考虑immutable对象,实在不行才暴露可修改的对象,并用同步措施来充分保护它。
  2. 其次是使用高级的并发编程构件,如TaskQueue,Producer-Comsumer Queue,CountDownLatch等等。
  3. 最后不得已必须使用底层同步原语时,只用不可重入的互斥器和条件变量,慎用读写锁,不要用信号量。
  4. 除了使用atomic整数之外,不自己编写lock-free代码,也不要用“内核级”同步原语。不凭空猜测“哪种做法性能更好”,比如spin lock vs mutex。
  • 使用互斥器的原则:用RALL手法封装mutex的创建,销毁,加锁,解锁这四个操作,只用不可重入的mutex,不手工调用lock()和unlock()函数,一切交给栈上的Guard对象的构造和析构函数负责。Guard的生命期正好等于临界区,Scoped Locking。在每次构造Guard对象的时候,思考一路上(调用栈上)已经持有的锁,防止因加锁顺序不同而导致死锁。次要原则:不使用跨进程的mutex,进程间通信只用TCP sockets。
  • 只用不可重入的mutex。
  • 条件变量的使用:
  1. 必须和mutex一起使用,条件变量的表达式的读写需受此mutex保护
  2. 在mutex已上锁的时候才能调用wait()。
  3. 把判断条件变量和wait放到while循环中。
  • 互斥器和条件变量构成了多线程编程的全部必备同步原语,用它们即可完成任何多线程同步任务,二者不能相互替代。
  • 不要用读写锁和信号量
  • 线程安全的singleton实现用pthread_once_t来保证执行一次实例化操作。
  • 我提倡正确加锁而不是自己编写lock-free算法,很多人误认为用锁会让程序变慢,其实真正影响程序性能的不是锁,而是锁争用。
  • 关于race condition ,chatgpt给出了延迟析构等解决构想,采用的是条件变量和mutex的协作。

标签:同步,变量,lock,加锁,线程,mutex,精要
From: https://www.cnblogs.com/wuyun--wy/p/17672439.html

相关文章

  • 线程安全的对象生命期管理
     编写线程安全的类不是难事,用同步原语保护内部状态即可。但是对象的生与死不能由对象自身拥有的mutex保护。racecondition:在即将析构一个对象时,从何而知此刻是否有别的线程正在执行该对象的成员函数?如何保证在执行成员函数期间,对象不会在另一个线程被析构?在调用某个对象的......
  • ConcurrentHashMap是如何保证线程安全的
    ConcurrentHashMap是concurrent包下的一个集合类。它是线程安全的哈希表。它是通过“分段锁”来实现多线程下的安全问题。它将哈希表分成了不同的段内使用了可重入锁(ReentrantLock ),不同线程只在一个段内存在线程的竞争。它不会对整个哈希表加锁。|初始化数据结构时的线程安全Has......
  • git不同分支同步代码,打patch补丁
    背景介绍一个代码管理者,不可避免的就是要将别人修改的代码同步到其他分支或其他仓库分支,因为不是所有人都有权限去合并的。合并代码有很多方式,比如直接文件夹覆盖、文件覆盖等。但上面的方法,繁琐还容易出错。写shell脚本也可以实现。这里主要想说,可以把内核打补丁的方法,......
  • mysql的GTID同步
    什么是GTID?GTID(GlobalTransactionID)是对于一个已提交事务的编号,并且是一个全局唯一的编号。GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。下面是一个GTID的具体形式:03a1eb63......
  • 解决antd Form的onChange方法改变的值与getFieldsValue获取的值不同步的问题
    项目场景:我想用antd写一个动态添加表单的Input框的功能,并且自动计算Input中的值,所以需要实时获取表单的数据。问题描述在onChange时使用form.getFieldsValue()方法获取的表单值是上次改变的值,与当前onChange改变的值不一致。这个时候我就在网上找解决方法。有的说可以在onChange......
  • c++并发编程实战-第2章 线程管控-读书笔记
    线程的基本管控每个应用程序都至少拥有一个线程,即运行main函数的线程,称为主线程,它由c++运行时系统启动。我们可以在软件运行中产生其他线程,它们以指定的函数作为入口函数。当main函数返回后,程序会退出;同样,当入口函数返回后,与之对应的线程结束。发起线程线程是通过构造std::thre......
  • Java - ThreadPoolExecutor线程池分析
    Java- ThreadPoolExecutor源码分析 1.为什么要自定义线程池首先ThreadPoolExecutor中,一共提供了7个参数,每个参数都是非常核心的属性,在线程池去执行任务时,每个参数都有决定性的作用。但是如果直接采用JDK提供的方式去构建,可见设置的核心参数最多就两个,这样就会导致对线程池......
  • java多线程
    实现Runnable接口publicclassMyRunnableimplementsRunnable{@Overridepublicvoidrun(){//线程执行的代码}}然后在主线程中创建一个线程对象,并启动该线程:Threadthread=newThread(newMyRunnable());thread.start();继承Thread类publicc......
  • 线程池在工作中的几种使用姿势
    线程池在开发中一定会用到,如果能像golang一样,java语言也有协程,也许java程序员就少了一种包袱。回归正题,我们聊下到底有哪些线程池的使用方式,总结有以下几种。JDK内置线程池Spring线程池自己魔改封装1、JDK内置线程池常用的有:我们看下最全的线程池参数,探究为什么阿里规......
  • 多线程与单线程执行的对比
    对比技术点:单线程:普通循环多线程框架:CompletableFuture多线程框架;ForkJoin50次对比实验 源码: packagecom.example.demo;importorg.apache.commons.lang3.time.StopWatch;importjava.util.ArrayList;importjava.util.List;importjava.util.concurre......