2016-08-03 87 views
1

波科RefCountedObject報價2個接口:Poco RefCountedObject線程安全嗎?

inline void RefCountedObject::duplicate() const 
{ 
    ++_counter; 
} 


inline void RefCountedObject::release() const throw() 
{ 
    try 
    { 
     if (--_counter == 0) delete this; 
    } 
    catch (...) 
    { 
     poco_unexpected(); 
    } 
} 

有了:

class Foundation_API RefCountedObject 
    /// A base class for objects that employ 
    /// reference counting based garbage collection. 
    /// 
    /// Reference-counted objects inhibit construction 
    /// by copying and assignment. 
{ 
public: 
    RefCountedObject(); 
     /// Creates the RefCountedObject. 
     /// The initial reference count is one. 

    void duplicate() const; 
     /// Increments the object's reference count. 

    void release() const throw(); 
     /// Decrements the object's reference count 
     /// and deletes the object if the count 
     /// reaches zero. 

    int referenceCount() const; 
     /// Returns the reference count. 

protected: 
    virtual ~RefCountedObject(); 
     /// Destroys the RefCountedObject. 

private: 
    RefCountedObject(const RefCountedObject&); 
    RefCountedObject& operator = (const RefCountedObject&); 

    mutable AtomicCounter _counter; 
}; 

需要注意的是: 可變AtomicCounter _counter;

我的問題是如果我在多線程中使用RefCountedObject是否安全?

在我看來,它不是因爲只有--_計數器是原子的,但如果(--_count)不是原子的,並且可能導致對已刪除對象的引用。 例如讓說我有2個線程A和B一個執行重複和其它釋放,執行順序是如下:

  • 乙開始執行釋放併到達--_計數器
  • 甲開始執行重複和達到++ _計數器
  • 此時_counter = 1個
  • 乙執行--_計數器並將結果返回到由IF(這是0 & &計數器是0現在)
  • B被搶佔和停止來評價之前分支語句(在IF)
  • 甲執行_counter ++並返回一個參考對象
  • 乙繼續和評價值爲0的分支語句和刪除對象

我們結束了一個具有引用已刪除的對象。 即使mutable關鍵字強制編譯器不優化_counter它不會幫助多線程

我是否錯過了什麼?

回答

1

嚴格看重複和孤立釋放,以上是正確的。然而,如果你有兩個線程,都有一個指向同一個RefCountedObject的指針,你應該在每個線程中有不同的AutoPtr實例(這意味着_counter大於1),或者,如果你共享如果至少有一個線程可以更改AutoPtr(這將導致調用release()),那麼它必須受互斥體保護。不用說在多個線程之間共享一個可變的AutoPtr是一種災難。

如果您通過手動調用duplicate()和release()(我不推薦)來管理RefCountedObject,則應該遵循POCO的引用計數規則,並且要非常小心。

因此,對於運行良好的代碼,RefCountedObject與AutoPtr一起可以安全地用於多線程應用。

+0

你說「在2個線程中分開的AutoPtr實例」。這是如何工作的?如果我們有兩個單獨的實例,我們將有兩個單獨的refCount,那麼我們如何才能在正確的時間刪除對象? – dhia