2011-10-03 15 views
16

मैं जावा में एक प्रोग्राम बना रहा हूं जो एक दूसरे के खिलाफ कुछ कारों को दौड़ता है। प्रत्येक कार एक अलग धागा है।क्या पूर्व-वृद्धि ऑपरेटर थ्रेड-सुरक्षित है?

जब कार दौड़ पूरी करती है, तो प्रत्येक व्यक्ति इस विधि को कॉल करता है। मैंने अलग-अलग टाइमर गति पर विधि का परीक्षण किया है, और ऐसा लगता है कि यह ठीक काम करता है। लेकिन मुझे एहसास है कि प्रत्येक थ्रेड परिवर्तनीय कारों को एक्सेस कर रहा है, कभी-कभी एक ही समय में (कम से कम उस दायरे पर दिनांक कमांड मुझे दे रहा है)।

तो मेरा सवाल है: क्या यह विधि थ्रेड-सुरक्षित है?

public static String completeRace() 
{ 
     Date accessDate = new Date(); 
     System.out.println("Cars Complete: " + carsComplete + " Accessed at " + accessDate.toString()); 
     switch(++carsComplete) 
     { 
      case 1: return "1st"; 
      case 2: return "2nd"; 
      case 3: return "3rd"; 
      default: return carsComplete + "th";  
     } 
} 

उत्तर

19

नहीं, आप java.util.concurrent.atomic.AtomicInteger की तरह कुछ का उपयोग करना चाहिए। इसकी getAndIncrement() विधि देखें।

+3

या वृद्धि से पहले कुछ पर सिंक्रनाइज़ करें। –

+1

@Ted: मैं शर्त लगाता हूं कि कुछ पर समन्वय करना अधिक महंगा है। –

+1

@Eric - मुझे आश्चर्य होगा अगर परमाणु इंटेगर ने कुछ बिंदु (शायद मूल कोड में) कुछ सिंकिंग नहीं किया। बेंचमार्क करना दिलचस्प होगा। परमाणु इंटेगर के स्रोत से, ऐसा लगता है कि यह एक परमाणु तुलना-और-सेट एल्गोरिदम पर निर्भर करता है जो तब तक पुनः प्रयास करता है जब तक कि कोई समस्या न हो। इसके लिए कोई बुरी स्थिति नहीं है; अत्यधिक थ्रेडेड परिदृश्यों में, मुझे लगता है कि यह यादृच्छिक समय पर बहुत धीमा हो सकता है। –

5

++ ऑपरेटर परमाणु नहीं है। यहां देखें http://madbean.com/2003/mb2003-44/। परमाणु संचालन के लिए आप AtomicInteger

AtomicInteger atomicInteger = new java.util.concurrent.atomic.AtomicInteger(0) 

उपयोग कर सकते हैं और हर बार आप चाहते हैं बढ़ाने के लिए आप atomicInteger.incrementAndGet() विधि है जो एक आदिम पूर्णांक रिटर्न कॉल कर सकते हैं। 0 परमाणु पूर्णांक के लिए डिफ़ॉल्ट प्रारंभिक मान है।

+0

मुझे अभी भी नहीं मिल रहा है क्यों परमाणु संचालन थ्रेड सुरक्षित हैं? क्या होता है जब दो धागे एक ही समय में सीएएस निष्पादित करते हैं ?? क्या यह दौड़ की स्थिति नहीं है ?? – hardik

+1

@ हार्डिक में कोई दौड़ की स्थिति नहीं है क्योंकि 'पहले होता है' (http://en.wikipedia.org/wiki/Happened- पहले) संबंध परमाणु परिचालनों द्वारा लागू किया जाता है और इसलिए परिणामस्वरूप थ्रेड सुरक्षा होती है। –

8

int पर पूर्व वेतन वृद्धि नहीं धागा सुरक्षित है, AtomicInteger का उपयोग जो ताला मुक्त है:

AtomicInteger carsComplete = new AtomicInteger(); 

//... 

switch(carsComplete.incrementAndGet()) 

BTW नीचे कोड है नहीं धागा सुरक्षित रूप में अच्छी तरह। क्या आप बता सकते हैं क्यों?

carsComplete.incrementAndGet(); 
switch(carsComplete.get()) 
+1

क्योंकि थ्रेड 1 स्विच स्टेटमेंट तक पहुंच सकता है, थ्रेड 2 तक पहुंचता है, जो बढ़ता है और इस प्रकार कारों के लिए बैकिंग स्टोर को बढ़ाता है, पूर्ण बिंदु पर, बैकिंग स्टोर के साथ दो बिंदुओं को दो बार बढ़ाया जाता है, प्रत्येक थ्रेड द्वारा एक बार बढ़ाया जाता है। –

+0

बिल्कुल, हालांकि इस बार कोई पुरस्कार नहीं ;-)। –

5
सी ++ में ऑपरेटर ++ रूप

ही परमाणु नहीं है।

यह वास्तव में 1 से अधिक अनुदेश हुड के नीचे निष्पादित किया जा रहा है (सिर्फ एक सरल ++i देखकर मूर्ख बनाया नहीं जा, यह load/add/store है) और के बाद से वहाँ 1 से अधिक अनुदेश तुल्यकालन के बिना शामिल है आप के साथ विभिन्न interleavings हो सकता है गलत परिणाम

आप जावा का निर्माण AtomicInteger उपयोग कर सकते हैं या आप पूरे विधि

1

प्रश्न है सिंक्रनाइज़ सकता है आप एक धागा सुरक्षित तरीके से carsComplete incrent करने की जरूरत है "पूर्व वेतन वृद्धि ऑपरेटर धागा सुरक्षित है?"

उत्तर: : क्यों नहीं ? शामिल निर्देशों की संख्या के कारण। परमाणु का मतलब एकल ऑपरेशन है, यहां लोड/एड/स्टोर ऑपरेशन करने की आवश्यकता है। तो एक परमाणु ऑपरेशन नहीं।

Same for post increment.