2014-11-27 9 views
15

इस कोड के साथ प्रोग्राम कभी-कभी "2" प्रिंट क्यों करता है?सी ++ परमाणु पढ़ने/गलतफहमी

int main() { 
    std::atomic<int> a; 
    a = 0; 

    std::thread t1([&]{++a;}); 
    std::thread t2([&]{a++;}); 
    std::thread t3([&]{ 
     a = a.load() + 1; 
    }); 

    t1.join(); 
    t2.join(); 
    t3.join(); 

    if (a != 3) { 
     std::cout << "a: " << a << std::endl; 
    } 
} 

मैं सोचा है std::atomic गारंटी देता है कि सभी कार्यों atomically किया जाएगा इसलिए यहाँ लिख (incrementing) एक स्मृति बाधा का उपयोग करेगा और हम हमेशा 3 धागे काम के अंत में होगा। मैंने कोड की खोज की है और पता चला है कि समस्या धागा t3 है लेकिन मुझे समझ में नहीं आता कि यह गलत क्यों है।

+8

'a = a.load() + 1' हालांकि केवल एक ऑपरेशन नहीं है। –

+0

++ ए और ए ++ परमाणु रूप से नहीं किया जाता है। आप http://en.cppreference.com/w/cpp/atomic/atomic/fetch_add – Rush

+1

@Rush पर इसके बारे में क्या देखना चाहते हैं? http://en.cppreference.com/w/cpp/atomic/atomic/operator_arith @JonathanPotter मुझे ऐसा लगा है, लेकिन कैसे फिर काम को बढ़ा देते है? मुझे लगता है कि इसे कम से कम एक पढ़ने की जरूरत है, है ना? तो 't3' में मैंने इसे अनुकरण करने की कोशिश की है लेकिन ऐसा लगता है कि यह गलत है क्योंकि @ पार्कयुंग-बाई ने कहा। तो मुझे लगता है कि समस्या यह है कि 't3' पुराने मान के साथ ओवरराइट करता है। –

उत्तर

26

t3, दो अन्य धागे के विपरीत, परमाणु जोड़ नहीं करता है। इसके बजाय, यह atomically a लोड करता है, गणित करता है एक अस्थायी पर भंडार है कि नए मूल्य वापस a को (जोड़ने 1) , और atomically। यह a को ओवरराइट करता है चाहे परमाणु परिचालनों के बावजूद हो सकता है।

  1. t1 या t2 atomically वेतन वृद्धि a जो अब करने के लिए 1.
  2. t3 बराबर है atomically लोड करता है 1.
  3. t1 या t2 atomically वेतन वृद्धि a है जो:

    तो तुम इस परिदृश्य पर हो सकता है अब 2 के बराबर 2.

  4. t3 previo पर एक गैर-परमाणु जोड़ करता है usly loaded value और परमाणु रूप से वापस स्टोर 2.
संबंधित मुद्दे