天天好味道

没钱没权没户口,靠走靠吼靠小狗
随笔 - 96, 文章 - 1, 评论 - 527, 引用 - 5

导航

<2009年11月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

公告

系分系分

留言簿(15)

随笔分类

随笔档案

文章档案

相册

我的链接

搜索

最新评论

阅读排行榜

评论排行榜

读到一篇关于线程安全的文章

如果说一个函数或者一个类是线程安全的,究竟代表什么意思呢?
我的第一反应是,在针对共享数据的访问上加锁。不过那篇文章
举了几个例子,很有意思。
第一,假设有一个队列,客户代码如下:
if(q->hasData()) Console.write(q->getFirstData());
GetFirstData是线程安全的,在针对队列数据访问的时候,queue进行了互斥。
但是以上的代码却不是线程安全的,如果在if成立以后,队列中的数据被其他线程
清除,那第二句调用就可能不合法了,比如getFirstData也许会搞一个异常出来。

第二,那就应该改成在getFirstData里自己判断是否有数据,把判断和取数据合并。
data = q->checkAndGetFirstData();
if(data)
Console.write(data);
这样起码不会有异常了。不过即使这样,还是有问题。这里的数据被复制到了data
上,如果write的时候队列中的数据被其他线程修改了,那这里打印出来的就不是
队列当时的真实数据。

只能再狠一点,
q->checkAndGetFirstDataThenExec(Console.write());
姑且不论这样写语法是否合理,总之这次是没问题了。

总结起来,其实线程安全是有不同的程度的。上面的三个例子,其实就是加锁的时间越来越长,
所以效率也在降低。

Python有一个著名的全局线程锁,导致Python里的多线程其实就是单线程,就是这种设计思路的
极致推广了。所以如果想用Python的多线程实现IO操作的并发,结果会很失望。


posted on 2009-10-21 18:55 jzhang 阅读(1722) 评论(3)  编辑 收藏

评论

# re: 读到一篇关于线程安全的文章

getFirstData如果内部也作了线程同步处理的话,应该不会出错的.
但它可能返回的对象是空.
也就是执行getFirstData时可能队列已经空了.
没有你的函数的原型,无法对问题进行判别了.
2009-11-11 17:50 | nscboy

# re: 读到一篇关于线程安全的文章

是的,getFirstData是线程安全的,但是他和hasData之间的过程没有保护。如果hasData说有数据,getFirstData返回一个空,虽然不会出错,但是程序逻辑却错了。
2009-11-12 10:22 | jzhang
标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]