(CopyOnWrite)在多线程环境中的陷阱(三)

类别:编程语言 点击:0 评论:0 推荐:

(CopyOnWrite)在多线程环境中的陷阱(一)

(CopyOnWrite)在多线程环境中的陷阱(二)

其实这个bug并不发生在:
  当UI主线程使用strLog中的字符串更新Edit,
  同时AddText被其他线程调用进行m_strStore +=操作
这种情况,

而是发生在:
 当UI主线程调用strLog中的析构函数,
 同时AddText被其他线程调用进行m_strStore +=操作
这种时候。

为什么会发生这种情况了?

首先我们看当UI主线程调用strLog中的析构函数的情况:
大概的程序流程是:
  a1. 检查引用计数是否大于1
     a2. 是, 引用计数减一,返回
  a3. 否则,释放字符串

注意,1-2步并不是一个原子操作,而且读取引用计数的时候并没有临界端保护。


然后我们再看AddText被其他线程调用进行m_strStore +=操作 时发生的情况
  b1. 判断引用计数是否大于1
     b2. 是,引用计数减一,分配新字符串并指向之
  b3. 否,在当前字符串继承上进行+=操作,如果空间不够,可能也要重新分配字符串。

同样,1-2步并不是一个原子操作,而且读取引用计数的时候并没有临界端保护。

这样考虑如下的执行序列:
 a1, //发现引用计数为2
 b1  //发现引用计数为2
 b2  //引用计数减一,分配新字符串并指向之
 a2  //引用计数减一,返回

在执行完b2的时候,引用计数已经为1了,但a线程接下来运行a2的时候,引用计数再次减一,变为0。同时,这块内存已经成为”孤魂野鬼“,不在被任何一个std::string对象所拥有,造成内存泄漏。

我们现在发现了问题,那么如何改正这个错误呢?

(CopyOnWrite)在多线程环境中的陷阱(四)

本文地址:http://com.8s8s.com/it/it28802.htm