注意指针修饰符的准确含义

首先从一起多线程无锁算法的事故说起,以下是一个无锁栈的实现测试,但在开-O2以上优化的情况下它却无法正常工作:

#include "lf_stack.h"
#include "kn_list.h"
#include "kn_time.h"
#include "kn_thread.h"
#include "kn_atomic.h"typedef struct lockfree_stack
{volatile kn_list_node *head;
}lockfree_stack,*lockfree_stack_t;static  void lfstack_push(lockfree_stack_t ls,kn_list_node *n)
{for( ; ;){  kn_list_node *lhead = ls->head;n->next = lhead;if(COMPARE_AND_SWAP(&ls->head,lhead,n))//if head unchange,set n to be the new headbreak;}
}static  kn_list_node* lfstack_pop(lockfree_stack_t ls)
{for( ; ;){  kn_list_node *lhead = ls->head;if(!lhead) return NULL;kn_list_node *next = lhead->next;               if(COMPARE_AND_SWAP(&ls->head,lhead,next)){lhead->next = NULL;return lhead;}}
}volatile int count = 0;
atomic_32_t c1 = 0;
atomic_32_t c2 = 0;struct element{kn_list_node node;int value;
};struct element *element_pool1;
struct element *element_pool2;lockfree_stack lf_stack;void *producer1(void *arg)
{printf("producer1\n");int i;while(1){for(i = 0; i < 10000000; ++i){struct element *ele =  &element_pool1[i];ATOMIC_INCREASE(&c1);lfstack_push(&lf_stack,(kn_list_node*)ele);}while(c1 > 0){FENCE();kn_sleepms(0);}}printf("producer1 end\n");return NULL;
}void *producer2(void *arg)
{printf("producer2\n");int i;while(1){for(i = 0; i < 10000000; ++i){struct element *ele =  &element_pool2[i];ATOMIC_INCREASE(&c2);   lfstack_push(&lf_stack,(kn_list_node*)ele);}while(c2 > 0){FENCE();kn_sleepms(0);}}return NULL;
}void *consumer(void *arg)
{printf("consumer\n");volatile struct element *ele;uint32_t tick = 0;while(1){if((ele = (struct element*)lfstack_pop(&lf_stack))){if(count == 0){tick = kn_systemms();}if(++count  == 5000000) {uint32_t now = kn_systemms();uint32_t elapse = (uint32_t)(now-tick);printf("pop %d/ms\n",count/elapse*1000);tick = now;count = 0;              }if(ele->value == 1)ATOMIC_DECREASE(&c1);else if(ele->value == 2)ATOMIC_DECREASE(&c2);elseprintf("%d\n",ele->value);  }}return NULL;
}int main(){element_pool1 = calloc(10000000,sizeof(*element_pool1));element_pool2 = calloc(10000000,sizeof(*element_pool2));int i;for(i = 0; i < 10000000; ++i) element_pool1[i].value = 1;for(i = 0; i < 10000000; ++i) element_pool2[i].value = 2;       lf_stack.head = NULL;kn_thread_t t1 = kn_create_thread(THREAD_JOINABLE);kn_thread_t t2 = kn_create_thread(THREAD_JOINABLE); kn_thread_t t3 = kn_create_thread(THREAD_JOINABLE); kn_thread_start_run(t1,producer1,NULL);kn_thread_start_run(t2,producer2,NULL); kn_thread_start_run(t3,consumer,NULL);      getchar();return 0;
}

表现就是consumer执行一定次数的pop之后死活也无法再弹出元素.不知道各位看官看出问题在哪没有.

当问题再次出现以后,我用调试器上去中断,consumer线程,断点正好在这行if(!lhead) return NULL;,lhead为NULL,我回到上一层栈查看实际上lockfree_stack.head字段并不是空,当我想查看lhead的地址时,显示无法查看寄存器地址.

那么问题就明确了,编译器把lhead存放在了寄存器,导致无法发现head实际已经被改变.那么问题来了,我明明将head标记为volatile的呀.

可是再仔细看看,volatile kn_list_node *head;修饰符在指针之前,意思是指向的是volatile变量,而我实际要的是,一个指针它本身是volatile的.ok,做相应的调整后kn_list_node * volatile head;,问题解决.

总之,对指针修饰符关键的一点就是,在*之前,修饰的是指向的目标.而在*之后才是修饰指针本身.

转载于:https://www.cnblogs.com/sniperHW/p/4190088.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298398.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通过 GitExtensions 来使用 Git 子模块功能

通过 GitExtensions 来使用 Git 子模块功能目录一、前言二、Git 子模块三、子模块更改提交四、更新子模块五、[附] 去除最近的提交记录独立观察员 2021 年 9 月 5 日一、前言众所周知&#xff0c;编程&#xff0c;尤其是面向对象编程的一个重要思想就是 “封装”&#xff0c;可…

Linux系列-Red Hat5平台下的Postfix邮件服务搭建(二)

咱们接着上次的说&#xff0c;本次没有小标题。想了半天也没想出个好名子来&#xff0c;因为这次我们要做三件事&#xff1a;1.搭建基于Postfix的webmail&#xff1b;2.设置用户别名和邮件群组&#xff1b;3.设置邮件大小、邮箱空间的限制。环境还是之前的&#xff0c;做之前可…

单片机断电后静态存储区里面还有数据吗_单片机启动流程和存储架构详解

最近在给公司的ADAS DCU做内存分配&#xff08;Memory Allocation&#xff09;&#xff0c;在这儿记录一下相关知识点&#xff0c;也算是给中文社区做贡献了。目录&#xff1a;1. ECU启动流程2. 存储空间解析3. TC397单片机的Memory Map和一些备注1. ECU启动流程图总比文字直观…

[WCF安全系列]认证与凭证:用户名/密码认证与Windows认证

如果要给认证下一个定义&#xff0c;我个人的倾向这样的定义&#xff1a;认证是确定被认证方的真实身份和他或她申明&#xff08;Claim&#xff09;的身份是否相符的行为。认证方需要被认证方提供相应的身份证明材料&#xff0c;以鉴定本身的身份是否与声称的身份相符。在计算机…

培养有见识的孩子,这6部适合孩子的纪录片,在家也能涨知识!

全世界只有3.14 % 的人关注了爆炸吧知识对孩子来说&#xff0c;好的纪录片就像打开了一扇新世界的大门&#xff0c;让他们了解更多世界的奇妙之处。BBC&#xff08;英国广播公司&#xff09;的纪录片题材广泛、制作精良。看这些经典的纪录片&#xff0c;既可以追溯上下数千年的…

Beta版本发布报告

项目名称学霸系统写手机客户端项目版本Beta版本负责人北京航空航天大学计算机学院 hots团队联系方式http://www.cnblogs.com/hotsbuaa/要求发布日期2014-12-28第一阶段基本功能已经完成&#xff0c;因此第二阶段的任务是&#xff1a;美化UI&#xff0c;修复接口&#xff0c;修复…

mysql连接主备_mysql主备配置方法

1. 选择两台机器(这里选的centos6.5 final)&#xff0c;安装相同版本的mysqlyum installmysql ;yum install mysql-server;2. 启动mysqlservice mysqld start3. 登录两个mysql&#xff0c;执行如下命令GRANT REPLICATION SLAVE,REPLICATION CLIENT on *.* to replmysql机器IP i…

linux下tar解压特定的目录

今天碰到一个客户的网站出问题&#xff0c;需要恢复&#xff1b;可我备份都是用打包的&#xff0c;如果要恢复某个目录&#xff0c;就需要全部解压&#xff0c;才能恢复&#xff1b;这样很费事。所以我请教了很多牛人&#xff0c;有没有解压压缩包里面特定的目录&#xff0c;可…

Dapr牵手.NET学习笔记:开篇

dapr&#xff0c;一个为分布式应用程序的运行时&#xff0c;为开发者在对接分布式组件时&#xff0c;提供了便利。使用dapr带来的好处可扩展性&#xff0c;因为它是通过sidecar的理概念来集成其他运行时的。同时dapr还提供了多种语言的SDK。关于dapr更多介绍&#xff0c;官方文…

vue 一个页面有点请求需要同时发送_前端性能优化,这些你都需要知道

来源: 海洋里的魔鬼鱼前言最近花了一些时间在项目的性能优化上&#xff0c;背后做了很多工作&#xff0c;但是最后依然没有达到自己想要的结果&#xff0c;有些失望&#xff0c;但是还是记录下自己的执着。性能优化总结&#xff1a;减少请求次数、减小资源大小、提高响应和加载…

男人能有什么错呢?

1 这上菜方式厉害了&#xff01;2 谁上学的时候还没转过笔了&#xff01;3 和朋友的塑料友情 图自别叫我P图仔4 非洲最致命的猫&#xff01;传说能撂倒长颈鹿&#xff01;大家估量一下&#xff01;5 狗子&#xff1a;你放开我好吗&#xff1f;&#xff1f;6 这位小姐姐真的很酷…

LDAP启动cacao提示Invalid file permission

问题处理步骤&#xff1a; 1、LDAP实例停止 2、DSCC控制台启动&#xff0c;提示cacao已停止…… 3、启动caocaorootrusky bin]# ./cacaoadm startInvalid file permission: [/home/ldap/dsee6/cacao_2/etc/opt/sun/cacao/instances/default/security] [rwxrwxr-x]. Problem val…

[019] C#基础:理解装箱与拆箱

.NET大牛之路 • 王亮精致码农 • 2021.08.27前面我们讲到 .NET 平台支持的两大数据类型&#xff1a;值类型和引用类型。值类型比引用类型更高效&#xff0c;因为它没有指针引用&#xff0c;不用分配在托管堆中&#xff0c;也不用被 GC 回收。但有时候你可能偶尔需要将一种类型…

H3C 5510 交换机DHCP设置

DHCP不能发现网络上非DHCP客户机已经在使用的IP地址&#xff1b;当网络上存在多个DHCP服务器时&#xff0c;一个DHCP服务器不能查出已被其它服务器租出去的IP地址&#xff1b;DHCP服务器不能跨路由器与客户机通信&#xff0c;除非路由器允许BOOTP转发。PC发出的广播包&#xff…

opentrace在mysql中使用_采用OpenReplicator解析MySQL binlog

Open Replicator是一个用Java编写的MySQL binlog分析程序。Open Replicator 首先连接到MySQL(就像一个普通的MySQL Slave一样)&#xff0c;然后接收和分析binlog&#xff0c;最终将分析得出的binlog events以回调的方式通知应用。Open Replicator可以被应用到MySQL数据变化的实…

雷军:有人说我写的代码像诗一样优雅~

全世界只有3.14 % 的人关注了爆炸吧知识整合整理&#xff1a;程序员的那些事&#xff08;id&#xff1a;iProgrammer&#xff09;雷军的代码像诗一样优雅↓↓↓有些网友在评论中质疑&#xff0c;说雷军代码不会是「屎」一样优雅吧。说这话的网友&#xff0c;也许是开玩笑的&…

国外网站评出对程序员最具影响的书籍清单

国外知名网站 stackoverflow 上有一个问题调查&#xff1a; 哪本书是对程序员最有影响、每个程序员都该阅读的书&#xff1f;这个调查已历时两年&#xff0c;目前为止吸引了153,432 人访问&#xff0c;读者共推荐出了 478 本书(还在增加)&#xff0c;其中最火的一本书《Code Co…

python大于小于_在Python中大于/小于Pandas DataFrames / Series之间的比较

如何在DataFrame和Series之间进行比较&#xff1f;我想掩盖DataFrame / Series中比其他DataFrame / Series中的元素更大/更小的元素. 例如,以下内容不会替换大于均值的元素 与nans虽然我期待它&#xff1a; >>> x pd.DataFrame(data{a: [1, 2], b: [3, 4]}) >>…

NodeJS学习笔记

通过js创建个简单的web服务器 var httprequire(http); http.createServer(function(req,res){ res.writeHead(200,{Content-Type:text/html}); res.end("server is up!"); }).listen(8000); console.log(listened on 8000); 推荐学习:Node入门 转载于:https://www.cn…

mysql分析日志_MYSQL 索引(三)--- SQL日志分析

慢查询日志Mysql 的慢查询日志是 Myql 提供的一种日志记录&#xff0c;用来记录在 Myql 中响应时间查过阈值的语句&#xff0c;具体指运行时间超过 long_query_time 值的 SQL&#xff0c;则会被记录在日志中。long_query_time 默认为 10&#xff0c;单位为秒。默认情况下&#…