博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用C语言内嵌汇编实现CAS
阅读量:4093 次
发布时间:2019-05-25

本文共 3119 字,大约阅读时间需要 10 分钟。

#include 
#include
#include
#include
#define MODE 4pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*本质就是CPU提供了一个叫做 CPMXCHG 的指令,可以让我们的比较操作和置换操作在一句指令内完成,因为指令是粒度最小的,所以就是原子操作。既然是原子操作,就不用加锁了。但是为了多线程下操作成功,必须使用while循环多次retry。虽然没有像mutex一样sleep-waiting有上下文切换开销,但是CAS会陷入busy-waiting,一直在忙等,类似自旋锁,造成cpu升高。需要评估锁的粒度后使用。*/unsigned long CAS(volatile unsigned int *addr, unsigned int old, unsigned int new){
/* https://www.felixcloutier.com/x86/cmpxchg: (* Accumulator = AL, AX, EAX, or RAX depending on whether a byte, word, doubleword, or quadword comparison is being performed *) TEMP ← DEST IF accumulator = TEMP (比较) THEN ZF ← 1; DEST ← SRC; ELSE ZF ← 0; accumulator ← TEMP; DEST ← TEMP; FI; Compares the value in the AL, AX, EAX, or RAX register with the first operand (destination operand). If the two values are equal, the second operand (source operand) is loaded into the destination operand. Otherwise, the destination operand is loaded into the AL, AX, EAX or RAX register. RAX register is available only in 64-bit mode. */ int ret = 0; __asm__ volatile (" lock; cmpxchg %2, %3" : "=a" (ret), "=m"(*addr) : "r" (new), "m" (*addr), "0" (old) : "cc" ); return ret==old;}void* add_cas(void *arg) {
int *count = (int *)arg; int old_count; for (int i = 0; i < 2500; i++) {
do {
old_count = *count; } while (!CAS(count, old_count, old_count + 1)); //} while (!__sync_bool_compare_and_swap(count, old_count, old_count + 1)); } return NULL;}void* add_atomic(void *arg) {
int *count = (int *)arg; for (int i = 0; i < 500; i++) {
__asm__ __volatile__ ("lock; add %1, %0" : "+m" (*count) : "g" (1) ); } return NULL;}void* add_generic(void *arg){
int *count = (int *)arg; for (int i = 0; i < 500; i++) {
(*count)++; } return NULL;}void* add_mutex(void *arg){
int *count = (int *)arg; for (int i = 0; i < 500; i++) {
pthread_mutex_lock(&mutex); (*count)++; pthread_mutex_unlock(&mutex); } return NULL;}#define MAXTHREADS 5int main(){
for (int i = 0; i < 500; i++) {
pthread_t pth[MAXTHREADS]; int *count = calloc(1, sizeof(int)); for (int i = 0; i < MAXTHREADS; i++) {
#if MODE == 1 pthread_create(pth + i, NULL, add_generic, count);#elif MODE == 2 pthread_create(pth + i, NULL, add_mutex, count);#elif MODE == 3 pthread_create(pth + i, NULL, add_atomic, count);#elif MODE == 4 pthread_create(pth + i, NULL, add_cas, count);#endif /* if MODE == 1 */ } for (int i = 0; i < MAXTHREADS; i++) {
pthread_join(pth[i], NULL); } printf("count: %d\n", *count); free(count); count = NULL; } return 0;}

转载地址:http://oecii.baihongyu.com/

你可能感兴趣的文章
JavaScript:时间日期格式验证大全
查看>>
pinyin4j:拼音与汉字的转换实例
查看>>
XML工具代码:SAX从String字符串XML内获取指定节点或属性的值
查看>>
时间日期:获取两个日期相差几天
查看>>
责任链模式 Chain of Responsibility
查看>>
高并发与大数据解决方案概述
查看>>
解决SimpleDateFormat线程安全问题NumberFormatException: multiple points
查看>>
MySQL数据库存储引擎简介
查看>>
处理Maven本地仓库.lastUpdated文件
查看>>
Kafka | 请求是怎么被处理的?
查看>>
Java并发编程1-线程池
查看>>
CentOS7,玩转samba服务,基于身份验证的共享
查看>>
计算机网络-网络协议模型
查看>>
计算机网络-OSI各层概述
查看>>
Java--String/StringBuffer/StringBuilder区别
查看>>
mySQL--深入理解事务隔离级别
查看>>
分布式之redis复习精讲
查看>>
数据结构与算法7-栈
查看>>
线性数据结构学习笔记
查看>>
数据结构与算法14-跳表
查看>>