并发编程2

103 阅读3分钟

原子性

原子性网上有很多定义,大意就是对于一个动作要么一起完成要么一个都不执行.那么如何实现原子性操作呢? 那就不得不提到cas, 那么cas是什么呢?

CAS 以及 利用cas的三个问题

cas全称是compare and swap, 随便网上查一下你会看到很多关于这个cas的描述.其实就是字面意思,比较和交换. 就是当且仅当预期值和内存值相同时做出修改并返回true,否则直接返回false.

aba问题

一个线程将共享变量由A变成了B,然后又变回了A,此时另一个线程来访问这个共享变量时发现该变量是A便以为该变量没有发生变化,但是实际上是发生了一系列的变化的,这就是aba问题.找了一些案例感觉描述这个问题最适合的还是开保险箱这个案例,两个人同事持有打开保险箱的钥匙,打开的条件是保险箱是关闭的状态,两人竞争开保险箱拿出里边的东西,a先一步打开保险箱拿出了东西,又把保险箱锁上了,这时b来了,他看见保险箱是关闭的以为箱子没有被打开过,自信的去打开箱子准备拿出里面的东西,可是结果是东西已经被拿走了.避免这种误会的办法就是加上版本号,a拿到东西后拿一个小本本在边上记录一下他已经拿走了这时b过来看到本子上有记录就不会浪费时间去尝试开锁拿东西拉.

cas自旋长时间未结束造成开销大的问题

解决CAS恶性空自旋的有效方式之一是以空间换时间这是一个网上找到的一个关于pause指令的方案的描述

pause指令能让自旋失败时cpu睡眠一小段时间再继续自旋,从而使得读操作的频率低很多,为解决内存顺序冲突而导致的流水线重排的代价也会小很多。 内存顺序冲突——当自旋锁快要释放的时候,持锁线程会有一个store命令,外面自旋的线程会发出各自的load命令,而此处并没任何 happen-before 排序,所以处理器是乱序执行,所以为了避免load出现在store之前此时会进行流水线清空再重排序,会严重影响cpu效率,Pause指令的作用就是减少并行load的数量,从而减少重排序时所耗时间.

那我理解的话使用队列应该也可以达到同样的效果.

多个共享变量操作的问题

这个就是个小技巧没啥好说的了, 如果你遇到多个共享变量的情况那你就想办法把他们合并就好拉.

以上原子性的描述以及cas主要的3个问题的一些个人理解,当然是借鉴了前辈们的成果.