2017-01-30 54 views
2

我在寫多線程套接字類。 BelowBounds()函數可以同時從多個線程中調用,我需要阻止使用互斥鎖。這段代碼是否是線程安全的?是原子增加和比較線程安全的

class UDPSocketHT 
{ 
public: 
    std::atomic<size_t> m_nSimultaneousRecvCalls; 
    std::atomic<size_t> m_nPendingOperations; 
    //... 
    bool UDPSocketHT::BelowBounds () 
    { 
     return (!m_nSimultaneousRecvCalls || (m_nPendingOperations + 1 <= m_nSimultaneousRecvCalls)) ? true : false; 
    } 
} 

或者我必須這樣寫?

bool UDPSocketHT::BelowBounds () 
{ 
    size_t x = m_nSimultaneousRecvCalls; 
    size_t y = m_nPendingOperations; 
    return (!x || (y + 1 <= x)) ? true : false; 
} 
+1

與你的問題無關,但如果你有一個導致「true」或「false」的三元表達式,那麼根本就不需要三元表達式。在你的最後一個例子中,你可以寫'return!x || (y + 1 <= x);' –

回答

5

你的兩個選擇都是不安全的。每個原子變量本身是原子的,但在單個語句中使用它們中的兩個不是。

你可以將你的支票包裝在一個互斥體中,或想出一種使用單個原子的方法。

std::atomic的哪些操作是原子操作?

  • operator=存儲一個新值以原子

  • load()operator T(使用在表達式)讀取值以原子

  • operator++遞增值以原子

  • compare_exchange_weak/strong檢查和原子地設置該值

  • more details

在表達式中使用兩個原子公司也不是原子的:a + b會讀a原子,然後閱讀b原子,但任何事情都有可能讀ab之間發生;在您閱讀b時,a可能已經具有其他值。