CAS无锁操作
https://coolshell.cn/articles/8239.html
主要讲的是《Implementing Lock-Free Queues》的论点,具体直接看论文最好。这里总结些要点。
CAS就是Compare And Swap。gcc可以调用:
__sync_bool_compare_and_swap
这段代码讲出无锁的两个关键手段:
EnQueue(x) //进队列
{
//准备新加入的结点数据
q = new record();
q->value = x;
q->next = NULL; do {
p = tail; //取链表尾指针的快照
} while( CAS(p->next, NULL, q) != TRUE); //如果没有把结点链在尾指针上,再试 CAS(tail, p, q); //置尾结点
}
一个就是CAS,一个就是Retry-Loop。
然后,还有一个ABA问题,就是在被抢占之前和之后数据地址没变,但是数据内容可能变了。解决思路就是加一个额外的状态来记录(也可以用记数)。
一个无锁队列的实现:
#include <sys/mman.h>
#include <string.h>
#include <iostream> class CircleQueue {
public:
CircleQueue(int queue_count) {
this->queue_size_ = queue_count * sizeof(void*) + sizeof(unsigned long*) * ;
this->queue_count_ = queue_count;
shm_ = mmap(NULL, queue_size_, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS , -, );
memset(shm_, , queue_size_);
head_ = (unsigned long*)shm_;
tail_ = (unsigned long*)((char*)shm_ + sizeof(unsigned long));
queue_ = (void**)((char*)shm_ + sizeof(unsigned long) * );
} ~CircleQueue() {
munmap(shm_, queue_size_);
} int PushOneThread(void* ap) {
if((int)(*head_ - *tail_) >= queue_count_) {
return ;//full
}
queue_[ *head_ % queue_count_ ] = ap;
*head_ = *head_ + ;
return ;
} bool IsEmpty() {
if(*head_ == *tail_) {
return true;
}
return false;
} int PopOneThread(void** ap) {
if(*head_ == *tail_) {
return ;
} if (ap == NULL) {
return -;
}
*ap = *(queue_ + *tail_ % queue_count_);
*tail_ = *tail_ + ;
return ;
} int PopMultiThread(void** ap, int retry) {
*ap = NULL;
for(int i = ; i < retry; ++i) {
volatile unsigned long tail = *tail_;
if(*head_ == tail) {
return ;
} int ret = __sync_bool_compare_and_swap(tail_, tail, tail + );
if(ret) {
*ap = *( queue_ + (tail % queue_count_));
return ;
}
}
return -;
}
private:
unsigned long* head_;
unsigned long* tail_;
void** queue_;
void* shm_;
int queue_size_;
int queue_count_;
};
这里的场景主要是一写多读。写的时候操作的是head,不需要加锁。读的时候,tail在改变的时候用上了CAS和retry-loop。 注意这里tail_只有在写的时候改变,而且只会往上加,所以不存在ABA问题。
p.s. 多进程通信的一个关键点,就是在于共享内存的时候,要确保所有的地址都是多进程共享的。所以这里存的指针,如果是多进程环境下,也应该是从共享内存中分配的。
CAS无锁操作的更多相关文章
- CAS无锁算法与ConcurrentLinkedQueue
CAS:Compare and Swap 比较并交换 java.util.concurrent包完全建立在CAS之上的,没有CAS就没有并发包.并发包借助了CAS无锁算法实现了区别于synchroni ...
- 链表的无锁操作 (JAVA)
看了下网上关于链表的无锁操作,写的不清楚,遂自己整理一部分,主要使用concurrent并发包的CAS操作. 1. 链表尾部插入 待插入的节点为:cur 尾节点:pred 基本插入方法: do{ pr ...
- java并发:AtomicInteger 以及CAS无锁算法【转载】
1 AtomicInteger解析 众所周知,在多线程并发的情况下,对于成员变量,可能是线程不安全的: 一个很简单的例子,假设我存在两个线程,让一个整数自增1000次,那么最终的值应该是1000:但是 ...
- CAS无锁机制原理
原子类 java.util.concurrent.atomic包:原子类的小工具包,支持在单个变量上解除锁的线程安全编程 原子变量类相当于一种泛化的 volatile 变量,能够支持原子的和有条件的读 ...
- (转载)java高并发:CAS无锁原理及广泛应用
java高并发:CAS无锁原理及广泛应用 版权声明:本文为博主原创文章,未经博主允许不得转载,转载请注明出处. 博主博客地址是 http://blog.csdn.net/liubenlong007 ...
- CAS无锁技术
前言:关于同步,很多人都知道synchronized,Reentrantlock等加锁技术,这种方式也很好理解,是在线程访问的临界区资源上建立一个阻塞机制,需要线程等待 其它线程释放了锁,它才能运行. ...
- CAS无锁实现原理以及ABA问题
CAS(比较与交换,Compare and swap) 是一种有名的无锁算法.无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(N ...
- 探索CAS无锁技术
前言:关于同步,很多人都知道synchronized,Reentrantlock等加锁技术,这种方式也很好理解,是在线程访问的临界区资源上建立一个阻塞机制,需要线程等待 其它线程释放了锁,它才能运行. ...
- CAS无锁模式
一.java内存模型:JMM 在内存模型当中定义一个主内存,所有声明的实例变量都存在于主内存当中,主内存的数据会共享给所有线程,每一个线程有一个块工作内存,工作内存当中主内存数据的副本当更新数据时,会 ...
随机推荐
- 删除linux上7天前后缀名.sql的文件
#!/bin/bash#delete the file of 7 days agofind /data/mysqlbackup/ -mtime +7 -name "*.sql" - ...
- spring mvc 注解详解
1.@Controller 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ...
- 多线程---iOS-Apple苹果官方文档翻译
本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址(2013年12月29日更新版) 多线程 技术博客http://www.cnblo ...
- perl6中函数参数(1)
sub F($number is copy){ $number++; say $number; } F(); #下面是错误的 sub F($number){ $number++; say $numbe ...
- 一个基于时间注入的perl小脚本
use strict; use warnings; use LWP::Simple; my %table_and_leng; ;;$count++){ #print "Test Table: ...
- %和format 细说
Python中格式化字符串目前有两种阵营:%和format,我们应该选择哪种呢? 自从Python2.6引入了format这个格式化字符串的方法之后,我认为%还是format这根本就不算个问题.不信你 ...
- Django rest framework 权限操作(源码分析)
知识回顾http://www.cnblogs.com/ctztake/p/8419059.html 这一篇是基于上一篇写的,上一篇谢了认证的具体流程,看懂了上一篇这一篇才能看懂, 当用户访问是 首先执 ...
- python基础===新式类与经典类
首先: Python 2.x中默认都是经典类,只有显式继承了object才是新式类 Python 3.x中默认都是新式类,不必显式的继承object 这两种类的区别: 新式类重定义的方法更多,当然这不 ...
- python近期遇到的一些面试问题(二)
1. 解释什么是栈溢出,在什么情况下可能出现. 栈溢出是由于C语言系列没有内置检查机制来确保复制到缓冲区的数据不得大于缓冲区的大小,因此当这个数据足够大的时候,将会溢出缓冲区的范围.在Python中, ...
- HTML5 audio标签自制音乐播放器
相关技能 HTML5+CSS3(实现页面布局和动态效果) Iconfont(使用矢量图标库添加播放器相关图标) LESS (动态CSS编写) jQuery(快速编写js脚本) gulp+webpack ...