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 在内存模型当中定义一个主内存,所有声明的实例变量都存在于主内存当中,主内存的数据会共享给所有线程,每一个线程有一个块工作内存,工作内存当中主内存数据的副本当更新数据时,会 ...
随机推荐
- 使用Apache Curator监控Zookeeper的Node和Path的状态
1.Zookeeper经常被我们用来做配置管理,配置的管理在分布式应用环境中很常见,例如同一个应用系统需要多台 PC Server 运行,但是它们运行的应用系统的某些配置项是相同的,如果要修改这些相同 ...
- 20155335俞昆《java程序设计》第十周总结
学号 2016-2017-2 <Java程序设计>第十周学习总结 ## 事实上网络编程,我们可以简单的理解为两台计算机相互通讯数据而已,对于程序员而言,掌握一种编程接口并使用一种编程模型相 ...
- 使用Sysmon分析宏病毒(Macros Downloader)
样本为一个Word文件,Virustotal地址: https://www.virustotal.com/#/file/f8aede78ad92bd28f5f699b677d7d5fd362c8be8 ...
- linux进程管理-定时定期执行任务
0.计划任务的命令: at 安排作业在某一时刻执行 batch 安排作业在系统负载不重时执行 crontab 安排周期性运行的作业 1.at命令用法: 安排命令或者多个命令在指定的时间运行一次 语法 ...
- PKUWC 2019 自闭记
PKUWC 2019 自闭记 Day -1 考前天天在隔壁的物竞教室划水(雀魂,能和吉老师一起玩的游戏都是好游戏),没有做题. Day 0 早上8:16的高铁,到广州南居然要6个小时...不知道福州和 ...
- java===java基础学习(16)---final
final-----概念 1.当不希望父类的某个方法被子类覆盖(override)时,可以用final关键字修饰. 2.当不希望类的某个变量的值被修改时,可以用final修饰.如果要用final,则必 ...
- win10安装提示“我们无法创建新的分区”
今日于笔记本安装win10时突然出现提示:我们无法创建新的分区.网上搜了不少建议,尝试了都无果. 由于我的笔记本是固态硬盘与机械硬盘混合,所以情况可能更加特殊. 最后成功的方法是: 1. 先将Win1 ...
- BZOJ 4241: 历史研究——莫队 二叉堆
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4241 题意:N个int范围内的数,M次询问一个区间最大的(数字*出现次数)(加权众数),可以 ...
- 12-4 NSString
原文:http://rypress.com/tutorials/objective-c/data-types/nsstring NSString 在本教程的内容可能我们已经看到过很多次了,NSStri ...
- 2.C 基础
C 基础 原文地址:http://rypress.com/tutorials/objective-c/c-basics OC 可以说是C语言的一个超集,这样你可以无缝的和C语言结合编程也就是你可以这两 ...