lockfree
为什么要lockfree
按我的理解, lockfree就是不去 调用操作系统给定的锁机制.
1. 会有system call, and system call is expensive; 比如pthread在linux里调用了futex.
2. 会失去控制, 接下来发生什么看操作系统心情了.
怎么做lockfree
不用操作系统给定的 同步机制, 而使用 硬件提供的机制, 简单说, 就是对 机器指令 的封装函数(right?).
首先一个是 compare-and-set. CAS/TAS
保证对某个变量的读出和修改是 原子的. 如下:
typedef LONG volatile tsl_t; #define MUTEX_SET(tsl) (!InterlockedExchange((PLONG)tsl, 1))
#define MUTEX_UNSET(tsl) InterlockedExchange((PLONG)tsl, 0)
`MUTEX_SET`返回1 表示已经锁住:
若此时 `tsl`为1, 表示已经被锁了, 置`tsl`为1, 返回原值的!, 即为0;
若此时 `tsl`为0, 表示锁可用, 置`tsl`为1, 返回1, 成功.
`MUTEX_SET`会被放入一个 loop中不断重试. 在gcc中, 可以用类似 `__sync_bool_compare_and_swap`的原语:
https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html
对应不同的硬件/编译器, 可以使用的cas不同. 例子: bdb: mutex_int.h. wiredtiger: gcc.h/msvc.h
memory barrier解决乱序
出于性能考虑, 编译器/硬件 会 reorder execution of your program. 对单线程程序 完全没有影响, 多线程就不行了.
编译器会reorder: 这个算内部矛盾? 毕竟都是软件的事
硬件(cpu) 会reorder: 对cpu来说, 数据放在三个地方: 寄存器/cpu缓存/主存.
LOAD - 从主存读入 到寄存器/缓存
STORE - 从寄存器/缓存 写入主存
本来 有 MESI - 缓存一致性协议(cache coherency) 保证 缓存-主存的一致性的:
https://en.wikipedia.org/wiki/MESI_protocol
modified - exclusive - shared - invalid
MESI是一个理论上的东西. 在实现上, 从性能考虑, 加入 store buffers, invalidate queues.
store buffer:
要解决的问题: 写一个shared/invalid cache line, 先广播 read-invalid message, 让别的处理器都invalid, 返回Invalidate Acknowledge, 然后才能写入cache.
解决方案:可以写入store buffer, 广播, 当前processor 接着做别的. 等收到所有处理器都invalid完了, 返回Invalidate Acknowledge, , 在写入cache. (异步执行的意思?)
给程序带来的新问题: write离开 buffer的时间 和 异步执行有关. 和程序原order无关.
invalidate queue:
要解决的问题: invalid 一个cache line挺慢的; 万一store buffer满了, processor 需要等待 某write释放 才能继续.
解决方案: 把 invalid 请求 入queue, 立即发送Invalidate Acknowledge, 然后慢慢执行queue. (还是异步?)
给程序带来的新问题:
Memory Barrier:
A store barrier will flush the store buffer, ensuring all writes have been applied to that CPU's cache.
A read barrier will flush the invalidation queue, thus ensuring that all writes by other CPUs become visible to the flushing CPU.
在做下一次store前, 保证store buffer被处理完 - membar之前的写 全部在cache里;
在做下一次load前, 保证invalidation queue被处理完 - 保证cache中没有过期数据.
full membar
read membar: flush invalidation queue
write member: flush store buffer
LFENCE/SFENCE/MFENCE
acquire/release
LoadLoad/LoadStore/StoreLoad/StoreStore: sparc
volatile: 对c来说, 用于阻止编译器过度优化. 如 替换 循环变量为 `while(true)` -- (这个我见过!); 改内存访问为 寄存器访问等.
http://lwn.net/Articles/250967/
http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_11
http://www.puppetmastertrading.com/images/hwViewForSwHackers.pdf
lockfree的更多相关文章
- Lock-Free 编程
文章索引 Lock-Free 编程是什么? Lock-Free 编程技术 读改写原子操作(Atomic Read-Modify-Write Operations) Compare-And-Swap 循 ...
- Lock,LockFree,MemoryBarrier,ConcurrentCollection
最近看并行编程书本的一些心得,简单记录下多线程和并行编程必知必会的几个概念,再次加深自己的理解. .NET Framework4提供了一个新的命名空间System.Collections.Concur ...
- 无锁数据结构(Lock-Free Data Structures)
一个星期前,我写了关于SQL Server里闩锁(Latches)和自旋锁(Spinlocks)的文章.2个同步原语(synchronization primitives)是用来保护SQL Serve ...
- 使用C++11实现无锁stack(lock-free stack)
前几篇文章,我们讨论了如何使用mutex保护数据及使用使用condition variable在多线程中进行同步.然而,使用mutex将会导致一下问题: 等待互斥锁会消耗宝贵的时间 — 有时候是很多时 ...
- Boost Lockfree
Boost Lockfree flyfish 2014-9-30 为了最大限度的挖掘并行编程的性能考虑使用与锁无关的数据结构来编程 与锁无关的数据结构不是依赖于锁和相互排斥来确保线程安全. Lockf ...
- 并发编程(三): 使用C++11实现无锁stack(lock-free stack)
前几篇文章,我们讨论了如何使用mutex保护数据及使用使用condition variable在多线程中进行同步.然而,使用mutex将会导致一下问题: 等待互斥锁会消耗宝贵的时间 - 有时候是很多时 ...
- boost::lockfree::queue多线程读写实例
最近的任务是写一个多线程的东西,就得接触多线程队列了,我反正是没学过分布式的,代码全凭感觉写出来的,不过运气好,代码能够work= = 话不多说,直接给代码吧,一个多消费者,多生产者的模式.假设我的任 ...
- 【Java并发编程】2、无锁编程:lock-free原理;CAS;ABA问题
转自:http://blog.csdn.net/kangroger/article/details/47867269 定义 无锁编程是指在不使用锁的情况下,在多线程环境下实现多变量的同步.即在没有线程 ...
- 读Lock-Free论文实践
论文地址:implementing Lock-Free Queue 论文大体讲的意思是:Lock-Base的程序的performance不好,并且a process inside the critic ...
随机推荐
- 试一下CANVAS
// 此应用源代码如下: document.getElementById("codetext").innerHTML = document.getElementById(" ...
- lucene历史版本地址
http://archive.apache.org/dist/lucene/java/
- iOS 上架被拒原因保存
一.后台一直在获取用户的定位,需要给用户电池消耗提示 Your app uses the Location Background mode but does not include the requi ...
- javascript中 for循环的应用
1.有一个棋盘,有64个方格,在第一个方格里面放1粒芝麻重量是0.00001kg,第二个里面放2粒,第三个里面放4,棋盘上放的所有芝麻的重量 <script> var sum=0; //一 ...
- pandas中将timestamp转为datetime
参考自:http://stackoverflow.com/questions/35312981/using-pandas-to-datetime-with-timestamps 在pandas Dat ...
- POJ 3624 Charm Bracelet(01背包)
Charm Bracelet Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 34532 Accepted: 15301 ...
- call
-------siwuxie095 call 调用另一个批处理程序或自身程序段,调用完,程序会回到原来 call 的地方继续执行 如果在脚本或批处理文件外使用 call,则不会在命令行起作用 语法 c ...
- AspNetPager分页控件使用方法
一.下载AspNetPager.dll 二.AspNetPager.dll复制于应用程序下的bin目录,打开解决方案,引用dll文件 三. 在工具栏中添加控件,这样可以支持拖拽使用 四. 要使用Asp ...
- python-mysqldb安装
出现错误 command 'gcc' failed with exit status 1 解决办法: yum install python-devel mysql-devel zlib-devel ...
- hdu 2586 How far away ?(离线求最近公共祖先)
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #i ...