在GotW 文章 #45中,Herb 声明如下:
void String::AboutToModify(
size_t n,
bool bMarkUnshareable /* = false */
) {
if( data_->refs > 1 && data_->refs != Unshareable ) {
/* ... etc. ... */
这个 if 条件不是线程安全的。一方面,评估甚至“data_->refs > 1”可能不是原子的;如果是这样,如果线程 1 尝试评估“data_->refs > 1”,而线程 2 正在更新 refs 的值,则从 data_->refs 读取的值可能是任何值——1、2,甚至是其他值这既不是原始值也不是新值。
此外,他指出 data_->refs 可以在与 1 比较和与 Unshareable 比较之间进行修改。
再往下,我们找到了一个解决方案:
void String::AboutToModify(
size_t n,
bool bMarkUnshareable /* = false */
) {
int refs = IntAtomicGet( data_->refs );
if( refs > 1 && refs != Unshareable ) {
/* ... etc. ...*/
现在,我知道两个比较都使用了相同的 refs,解决了问题 2。但为什么是 IntAtomicGet?我在该主题的搜索中一无所获——所有原子操作都集中在读、修改、写操作上,在这里我们只是读一下。那我们能不能...
int refs = data_->refs;
...最终可能只是一条指令?