文档章节

话说同步机制

厉力文武
 厉力文武
发布于 2017/05/08 11:47
字数 2303
阅读 199
收藏 1

    天舟一号发射国产航母下水C919成功首飞好事一桩接一桩,中国人认定要干的事情没有干不成的实在可喜可贺。这拨沙尘过去了,天真蓝又能大口喘气了真舒服,半夜里骑小蓝车去麦当劳买那么大鸡排,店里竟然坐着一大半客人在用餐,望京国贸CBD金融街上地西二旗写字楼的灯火通明时刻提醒人们这里是繁华的国际大都市,任何不努力都只是借口,什刹海三里屯也灯火通明,算了吧那地少去,喝的不是酒全是寂寞。

    做软件开发的总是躲不过同步机制这个话题,并发处理免不了对公共数据进行操作,不认真对待它总找你麻烦,一段代码写的漫天飞舞天花乱坠结果折在同步上是一件很憋屈的事情,一个木桶能盛多少水是由最短的那块木板决定的,没错同步机制处理不好这就是瓶颈。同步机制这个话题有点大,三言两语说不清,需要耐下心慢慢研究,吐血推荐《UNIX网络编程(第2版)》第1卷以及第2卷之进程间通信,作者史蒂文博士,全宇宙知名网络专家教育家,治学严谨而且文章通俗易懂,可惜天妒英才令人扼腕叹息,上帝身边缺个程序猿。没读过史蒂文博士著作的攻城狮不是好码畜,必须精读,必要时动手操练一下受益匪浅绝对一生受用。

    同步机制不能不说posix和system v这两种标准,posix比较新方便移植也更标准化一些,在没有竞争条件的情况下,保持用户态调用也更轻量化一些,system v相对老些,每次调用都会进出内核,性能方面略处下风,不追求极致的话哪个都行全凭个人习惯和喜好。主要的同步机制包括锁(自旋锁、互斥锁、条件锁、读写锁)、信号灯(信号量)、记录锁(文件锁),接下来谈谈个人的认识和理解。

    先撇清一个问题,有童鞋说原子操作也能实现并发处理对公共数据的排他性操作呀,这话没毛病,原子操作是利用CPU单一指令执行中不可中断的特性实现的,即必须确保对数据的操作在一个指令中完成,显然对一个变量的“读改写”在一条CPU指令里完成是不现实的,因此需要一种机制来保障,由于同步机制考量的是对一系列计算过程或一块代码区间执行的独占性操作,所以这个话题就不在这里讨论了。

    自旋锁的意义在于对超短时间内的操作进行轻量级锁定,它会一遍一遍尝试获取锁定,容易造成CPU高占用,并且锁定区间存在阻塞操作的话还将导致潜在的死锁风险,因此对于大块逻辑计算完全不适用,自旋久了容易晕,一晕就容易吐,一吐就容易虚,一虚就容易亏,一亏就需要补~

    互斥锁好东西效率真棒没的说,上锁的干活等锁的挂起完全不占用任何计算资源,有两个属性超级有用,一个是PTHREAD_PROCESS_SHARED,把含有该属性的互斥锁放在共享内存中供多个进程分别映射到各自地址空间中,竟然没有比线程共享在效率上有明显衰减,真是了不起;另一个是PTHREAD_MUTEX_RECURSIVE,同一线程下多次锁定不会导致阻塞,在团队开发工作中有时无法彻底杜绝嵌套调用,互斥量就显示出它的价值了,但互斥量必须成对出现,而且也是有系统开销的喔,另外上述两个优惠政策不能同时享受,最终解释权归操作系统。

    条件锁跟互斥锁基本一回事只是增加了条件判断,满足才触发下面的流程,否则挂起等待,节省了大量轮询的资源消耗。唤醒方式分单播与广播,在明确条件等待者身份唯一性的情况下单播已经够用了,否则推荐更可靠的广播方式发送,假如对唤醒还是不放心的话还可以调用定时等待,条件满足或超时立即返回,这样够放心了吧。

    读写锁是在互斥锁基础上对特定应用场景的优化,写写之间互斥读写之间互斥读读之间共享,总结起来就是数据变动就独占不变就共享,效率比互斥锁差一些也是完全可以理解和接受的。

    信号灯(信号量或信号量集合)网上有不少讨论,有认为是一回事只是叫法不同而已,也有认为是二回事,个人支持第二种,因为我们的语文真的是语文老师教的,回到这个严肃的话题上说说区别。灯有两种状态开和关或是亮和灭,非开即关不是亮就是灭,半开半关半亮半灭的灯从来没见过;量代表一个值,可以是十可以是百可以是千,总之不是非此即彼的关系,假设量是一定的,借一个少一个,借光了只能等着,有人还回来了才能再往出借,所以说信号灯是信号量初始为一时的特例,信号量是对信号灯的衍生和扩展,能够解决更加复杂的资源分配问题,长这么大还是第一次被自己清晰的条理和超强的概括能力震撼到。信号灯分两种有名的和无名的,无名比有名快,posix比system v快,无名的用在线程间,放共享内存被映射后进程间可用,有名的原本就为进程间设计的。另外system v还分带不带undo标识的,不带的更快点,带的如果进程over了可以自动释放。两套标准分别提供各自的API,并包含非阻塞的调用方式。

    记录锁(文件锁)都是对文件进行操作,区别是粒度不同,记录锁是锁文件区间,文件锁是把对文件的操作当成锁操作并进而转化成独占操作而已,因此锁效率较差用的也越来越少了,但对文件中的部分区间上锁进行读写操作还是有存在和使用的价值的。

    下面两张图是尊敬的史蒂文博士对上述各种同步机制在Solaris上测试的结论数据,鉴于上世纪末计算机的计算速度和处理能力,各项数值在当下已经没有实际参考意义,但数值间的差值变化与发展趋势还是能够真实反映各自效率的,具有重大的参考价值。

                  

                 

    总结了若干条在使用同步机制时需要注意的事项。

    第一:上锁和解锁务必成对出现且尽量放置在相同的调用层级关系中;

    第二:坚持谁上锁谁解锁原则,适用在进程、线程、协程乃至于函数和方法;

    第三:原则上锁定区间越小越好时间越短越好,兼顾锁定频率适当优化代码;

    第四:锁定区间强烈反对任务阻塞操作即便自认为可控也绝不是明智的做法;

    第五:进程间同步务必注册回调函数以保证进程或正常或异常终止时能释放锁;

     第六:业务流程侧实现锁操作而非在功能算法侧以减少嵌套调用规避死锁风险;

    第七:不同应用场景选择适合的同步机制对并发处理效率的提升效果十分明显;

    第八:妥善维护好锁属性与状态以及远离非法操作是保证并发处理的重要基础;

    总结一下中心思想,对于如何提升并发处理效率最好的思路不是选择具体哪种同步机制,也不是怎么组织优化代码,更不是简单增加进(线)程数,而是压根就不用任何同步机制。之前《高性能服务优化》一文中承诺单聊下同步机制,这篇作业就算是兑现了,文中所涉及的代码实现在http://git.oschina.net/gonglibin/GlbLib-1.0.0中都可以找到,包含封装与测试,需要的自己扒吧。

    坚持梦想不忘初心送给今天的自己和各位小伙伴儿,2017年5月8号。

© 著作权归作者所有

厉力文武
粉丝 29
博文 86
码字总数 81619
作品 0
朝阳
程序员
私信 提问
我的架构演化笔记 4 :MongoDB 增加集群机制

话说,我正打算加入新的功能。 有这么一段对话。 表弟“貌似一台MongoDB主机容易挂掉,如果停电了或者硬盘损坏了怎么办?”咱可是要提供99.99999999999的可靠性啊。 我“别慌,咱有master-sl...

强子哥哥
2014/06/03
0
0
最近学习了 mysql 跟oracle 锁机制,java同步 前辈们,能不能指点1-2啊,这块mianshi被问到好多次之前

如题,年后打算再换家公司,把锁机制 java同步 学习了下,不知道成果如何,有木有这方面试题,检验下自己所学额,所有相关题目 全部解答,不会的我会去找书或请教别人的 话说 有点喜欢mians...

你是错的我恒对
2014/01/18
263
1
Linux的相关资源帖

http://www.kerneltravel.net/?page_id=8 2.6内核模块编程实例指导 内核模块编程之入门(一)-话说模块 内核模块编程之入门(二)—必备知识 内核模块编程之入门(三)-模块实用程序简介 内核...

AlphaJay
2010/05/21
213
0
线程池(领导者-追随者,生产者-消费者等)小结

领导者/追随者模型(Leader/Followers) 这几天翻了些文章,发现对领导者/追随者模型说的比较少,下面就这个模型打个比方: 话说一个地方有一群有组织无纪律的人从事山贼这个很有前途的职业。...

长平狐
2013/01/06
649
0
话说现在有多少人会关注代码质量呢?你会不会去关注呢?

据了解开源社区的有很好的代码评审机制从而保证质量,而在实际开发中,话说现在有多少人会去关注代码质量这种非功能性的需求? 在功能性需求和非功能性需求如何取舍呢?

donhui
2014/08/22
79
4

没有更多内容

加载失败,请刷新页面

加载更多

代理模式

//分静态代理和动态代理,区别:是否再编译时知道被被代理的对象 //思想,被代理类将自己的处理交给代理类,代理类可以添加一些新的功能,之后有代理类和客户端交互 https://www.cnblogs.co...

南桥北木
31分钟前
2
0
Spring系列教程七: Spring 整合mybatis的四种方式

一、使用注解实现整合mybatis 项目目录如下 第一步、导入jar包 <build> <resources> <!-- mapper.xml文件在java目录下 --> <resource> ......

我叫小糖主
37分钟前
6
0
阿里P7架构师:这些技术点没搞懂,我劝你不要跳槽!

阿里P7架构师架构师:这些技术点没搞懂,我劝你不要跳槽! 哪些技术点呢? 废话不多说,技术点全在下面这6张图里面了! 1.怎么看源码? 2.分布式 3.微服务 4.性能优化 5.工程化 粉丝福利:一...

别打我会飞
55分钟前
6
0
易错题

父类必须有一个无参构造,不然会报Implicit super constructor Parent() is undefined. Must explicitly invoke another constructor...

architect刘源源
今天
1
0
使用Json4s 将带有Timestamp的对象转json时 变为所在时区

在有Timestamp属性的对象转json时 最后出来的时间会减小8小时,是因为变成了0时区,需要将隐式转换中添加设置本地时区 import org.json4s.{DefaultFormats, Formats}import org.json4s.jac...

可达鸭Go
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部