chrome-RefCountedThreadSafe所谓的线程安全是什么?

来源:互联网 发布:linux c 创建文件夹 编辑:程序博客网 时间:2024/05/16 12:59

RefCountedThreadSafe的引用计数是原子操作的,所以网上查到的统一的说法线程安全,RefCountedThreadSafe也有很多非原子操作,它所谓的线程安全是什么意思
比如用scoped_refptr操作RefCountedThreadSafe跨线程会线程安全吗?

写个简单的示例测试:

class Test : public base::RefCountedThreadSafe<Test>{public:    Test(){}private:     friend class base::RefCountedThreadSafe<Test>;    ~Test()    {        int i = 0;    }};scoped_refptr<Test> g_pTest;DWORD WINAPI ThreadProc1(LPVOID lpParameter){    g_pTest = NULL;    return 0;}DWORD WINAPI ThreadProc2(LPVOID lpParameter){    scoped_refptr<Test> pOther;    if (g_pTest)    {        pOther = g_pTest;    }    return 0;}void Fun(){    g_pTest = new Test;    DWORD dwThreadId1 = 0;    ::CreateThread(NULL,0,ThreadProc1,NULL,0,&dwThreadId1);    DWORD dwThreadId2 = 0;    ::CreateThread(NULL,0,ThreadProc2,NULL,0,&dwThreadId2);}

上面是两个线程,一个测试函数,先在ThreadProc1和ThreadProc2中分别设置断点,一般会先断在ThreadProc1中, 初始g_pTest的引用计数为1,见下图:
这里写图片描述

单步调试跳转进去,在scoped_refptr<T>& operator=(T* p)
设置个断点,如下图:
这里写图片描述

此时,切换到ThreadProc2线程:
因为g_pTest还没执行ptr_赋值,所以ptr_是有值的,即if (g_pTest)是OK的,因为有pOther = g_pTest;,scoped_refptr同样会走到赋值操作scoped_refptr<T>& operator=(T* p)中,注意,这是在ThreadProc2线程中,我们在它执行AddRef(即引用计数还没有+1)之前断下:
这里写图片描述

此时,切换回ThreadProc1线程:
让ThreadProc1执行完它的赋值再delete操作,最终走到Test的析构函数,即0x01c85588这个地址被释放了
这里写图片描述

此时,切换到ThreadProc2线程:
它要执行p->AddRef,因为p(0x01c85588),这个地址已经被释放,那么这个 ptr_->倒底会出现什么样的错误,就不得而知了,
这里写图片描述
最后在pOther释放时, 弹出如下框:
这里写图片描述
这里写图片描述

所以scoped_refptr这么使用RefCountedThreadSafe应该不是线程安全的,同样测试WeakPtr,在is_valid_ = false之前,让WeakPtr先get,是有效的,但实际对象已被析构,也会OVER,
但是如果我们在调用线程 先AddRef,在其他线程去Release,感觉还是线程安全的,比如典型的Task

原创粉丝点击