免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 7690 | 回复: 16
打印 上一主题 下一主题

[C++]双重IF能带来lock调用开销最小的疑问。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-09-27 08:47 |只看该作者 |倒序浏览
本帖最后由 ctsweeper 于 2011-09-27 09:49 编辑

volatile T* p=0;
T*GetInstance()
{
if(p==NULL)
{
    lock();
    if(p==NULL) p=new T;
    unlock();
}
return p;
}

源自《程序员的自我修养》

我觉得把第二个if去掉也没有什么区别。
请明白人解释一下,拜谢。

论坛徽章:
0
2 [报告]
发表于 2011-09-27 08:53 |只看该作者
另外,这个问题的背景是多线程的调度。

论坛徽章:
0
3 [报告]
发表于 2011-09-27 09:13 |只看该作者
多线程+系统调度,带来的问题是你的代码可能在任意位置被系统挂起

如果线程1的第一个if判断为NULL,然后被挂起

然后线程2执行上面代码,发现也是NULL,就会new一个对象出来

稍后系统恢复线程1的状态,并继续执行线程1,线程1就又会new一个对象




凡是涉及多线程及调度,都会有一些非常微妙的问题,需要我们仔细地设计和实现

论坛徽章:
17
水瓶座
日期:2013-08-29 12:09:27白羊座
日期:2014-08-07 12:36:42丑牛
日期:2014-07-24 12:44:41寅虎
日期:2014-04-16 16:15:33寅虎
日期:2014-03-12 09:28:43摩羯座
日期:2014-03-06 13:22:04技术图书徽章
日期:2014-03-06 11:34:50天蝎座
日期:2014-01-09 11:31:44寅虎
日期:2013-12-27 17:01:44双子座
日期:2013-12-27 12:32:29双子座
日期:2013-12-25 09:03:33丑牛
日期:2013-12-24 16:18:44
4 [报告]
发表于 2011-09-27 09:30 |只看该作者
第一个if的作用是为了防止p已经分配了空间还无端的获取锁,造成效率降低。
第二个if楼上已经讲的很明白了,就是防止竞争条件。

论坛徽章:
0
5 [报告]
发表于 2011-09-27 10:05 |只看该作者
3楼的大哥解释是线程2会比线程1先new,我觉得会线程1比线程2先new,是不是我们对lock()的理解不一致。我理解lock()是独占这个资源,既然独占了,肯定会先new完之后,再unlock()给其他线程用。
另外,如果去掉第二个if带来的不好的后果我还是没有想通

论坛徽章:
0
6 [报告]
发表于 2011-09-27 10:12 |只看该作者
我觉得他写错了,
不是 volatile T* p=0;
而是 T * volatile p = 0;

因为这里,并不是要p指向的地方为volatile,
而是p本身。

不知道他的修养不够,还是我的修养不好。

论坛徽章:
0
7 [报告]
发表于 2011-09-27 10:27 |只看该作者
我觉得他写错了,
不是 volatile T* p=0;
而是 T * volatile p = 0;

因为这里,并不是要p指向的地方为 ...
AD8018 发表于 2011-09-27 10:12



    我觉得书上写的是对的,照你的意思,他写成T volatile* p = 0;才不对吧。

我觉得你的写法和你的想法也正好相反了。

请聚焦一下主题- -!

论坛徽章:
0
8 [报告]
发表于 2011-09-27 10:29 |只看该作者
我觉得书上写的是对的,照你的意思,他写成T volatile* p = 0;才不对吧。

我觉得你的写法和你 ...
ctsweeper 发表于 2011-09-27 10:27


你要补充下基础知识了----  T volatile* p 和 volatile T *p是一个意思。

论坛徽章:
0
9 [报告]
发表于 2011-09-27 10:35 |只看该作者
你要补充下基础知识了----  T volatile* p 和 volatile T *p是一个意思。
AD8018 发表于 2011-09-27 10:29



    哦哦,对的,查了一下,你说的没错。

不过这个不是焦点,还请指点一下我关注的东西。

论坛徽章:
17
水瓶座
日期:2013-08-29 12:09:27白羊座
日期:2014-08-07 12:36:42丑牛
日期:2014-07-24 12:44:41寅虎
日期:2014-04-16 16:15:33寅虎
日期:2014-03-12 09:28:43摩羯座
日期:2014-03-06 13:22:04技术图书徽章
日期:2014-03-06 11:34:50天蝎座
日期:2014-01-09 11:31:44寅虎
日期:2013-12-27 17:01:44双子座
日期:2013-12-27 12:32:29双子座
日期:2013-12-25 09:03:33丑牛
日期:2013-12-24 16:18:44
10 [报告]
发表于 2011-09-27 10:36 |只看该作者
回复 5# ctsweeper

第一个if到lock()之间,有时间窗,操作系统可以进行任务调度。
假设线程A运行了第一个if,判断为真,这个时候任务调度了,那么恢复执行的时候就是在lock()这里。

这个时候线程B获得了运行的机会,他进入该临界区,由于p还是NULL,而且也没有人获取到锁,所以它lock()成功,分配空间给p,然后unlock退出。

操作系统继续任务调度,A再次获得运行机会,恢复执行是在lock(),然后假如没有第2个if,那么直接再次分配p,上次分配的内存泄露。然后unlock退出。

第2个if就是防止这种竞争条件而出现的!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP