转载

Lock Free中的Hazard Pointer(中)

看过上篇的朋友,可能会认为:这不就是 Smart Pointer 么?于是可能写出这样的代码:

#include<iostream> #include<thread> using namespace std; class SmartPointer { public:   SmartPointer(int *p)   {     pointee_ = p;     ref_counts_ = 0;   }   int *pointee_;   int ref_counts_; }; SmartPointer sp(new int(1)); void Reader() {   ++sp.ref_counts_;   cout<<*(sp.pointee_)<<endl;   --sp.ref_counts_; } void Writer() {   if (sp.ref_counts_ == 0)     delete sp.pointee_; } int main() {   std::thread t1(Reader);   std::thread t2(Reader);   std::thread t3(Reader);   std::thread t4(Writer);   t1.join();   t2.join();   t3.join();   t4.join();   return 0; } 

然而事实上,这样做是错的。其中的 race condition 请读者自行分析。

那么, Hazard Pointer ( HP )和 Smart Pointer ( SP )有什么区别呢?它们的共同点就是管理对应对象的生命周期,然而这两者有本质的区别, HP 是线程安全的,而 SP 不是。

在 HP 中,每个读线程维护着自己的 HP list ,这个 list ,只由该线程写。因此,它是线程安全的。该 list 会(可以)被其他线程读。

每个写线程维护自己的 retire list ,该 retire list 只由该写线程进行读写。由于写线程可以读其他所有读线程的 HP list ,这样,差集(在自己的 retire list ,但是不在所有读线程的 HP list 里的指针),就是可以安全释放的指针。

而 SP ,则被多个线程读写, 18、19 两行也无法做成原子操作,因此, SP 和 HP 有本质的区别,使用 SP 的程序往往需要搭配使用锁等设施来保证线程安全。

正文到此结束
Loading...