2010-08-16 18 views
17

मेरे पास दो धागे हैं। एक वर्ग की अद्यतन विधि को आमंत्रित करता है जो एक चर को संशोधित करता है। दूसरा एक वर्ग की अद्यतन विधि को आमंत्रित करता है जो चर को पढ़ता है। केवल एक धागा लिखता है और एक (या अधिक) धागे उस चर को पढ़ते हैं। समेकन के मामले में मुझे क्या करने की ज़रूरत है, क्योंकि मैं बहु-थ्रेडिंग के लिए नया हूं?जावा दो धागे के बीच एक चर साझा करें

public class A 
{ 
    public int variable; // Does this need to be volatile? 
     // Not only int, could also be boolean or float. 
    public void update() 
    { 
     // Called by one thread constantly 
     ++variable; 
     // Or some other algorithm 
     variable = complexAlgorithm(); 
    } 
} 

public class B 
{ 
    public A a; 
    public void update() 
    { 
     // Called by another thread constantly 
     // I don't care about missing an update 
     int v = a.variable; 
     // Do algorithm with v... 
    } 
} 

धन्यवाद,

+2

नीचे दिए गए कई उत्तरों का मानना ​​है कि आप पूर्णांक कुशलता कर रहे हैं जिसे 'परमाणु इंटेगर' वर्ग द्वारा नियंत्रित किया जा सकता है। कुछ और जटिल के लिए, 'सिंक्रनाइज़' ब्लॉक या 'java.util.conccurent.locks.Lock' – justkt

उत्तर

17

यदि कोई और केवल एक धागा है जो variable पर लिखता है तो आप इसे volatile बनाने से दूर हो सकते हैं। अन्यथा AtomicInteger के साथ उत्तर देखें।

केवल volatile केवल एक लेखन धागे के मामले में काम करेगा क्योंकि केवल एक लेखन धागा है इसलिए यह हमेशा variable का सही मूल्य है।

+0

यह मेरा मुद्दा था। मुझे पता है कि केवल एक धागा इसे संशोधित करता है लेकिन इसे पढ़ने के कई धागे हो सकते हैं। – Dave

+0

@ डेव - ठीक है, यही कारण है कि मैंने यह जवाब पोस्ट किया। यदि आपका बहु-थ्रेडिंग सरल है, केवल एक थ्रेड लिखता है और आपके पास केवल एक वैरिएबल है जो इसे अन्य धागे पढ़ने के लिए लिखता है, आपको जटिल समाधान की आवश्यकता नहीं है, अस्थिर int चर होगा। एक सामान्य मामले में आप शायद ताले, synchonized या AtomicInteger चाहते हैं। लेकिन आपका प्रश्न लेखक धागे की संख्या और इसमें शामिल चर के नंबर पर काफी विशिष्ट था। अन्य उत्तरों पर वोटों से डरो मत। यदि मेरा समाधान आपकी आवश्यकताओं को सुइट करता है, तो इसे स्वीकार करें। – hidralisk

+0

बहुत बहुत धन्यवाद मुझे बस एक दूसरी राय की जरूरत है। मैं समेकन पैकेज में परमाणु चर और अन्य उपहारों के बारे में कभी नहीं जानता था कि मैं यहां खुश लोगों को समझाने के लिए बहुत दयालु हूं। यह भविष्य में मेरे लिए मूल्यवान साबित हो सकता है। – Dave

8

इतना ही नहीं variablevolatile होना चाहिए, लेकिन आप भी ++variable के बाद से some sort of synchronization के साथ अपने update समारोह की रक्षा करना चाहते हैं एक परमाणु कॉल नहीं है। यह सब के बाद,

variable = variable + 1; 
variable = variable + 1; 

पर केवल वाक्य रचनात्मक चीनी है जो परमाणु नहीं है।

आपको किसी भी प्रकार के lock में चर पढ़ने वाले किसी भी कॉल को भी लपेटना चाहिए।

वैकल्पिक रूप से, AtomicInteger का उपयोग करें। यह इस तरह की चीज के लिए बनाया गया था (केवल पूर्णांक परिचालन के लिए)।

public class A 
{ 
    // initially had said volatile wouldn't affect this variable because 
    // it is not a primitive, but see correction in comments 
    public final AtomicInteger variable; // see comments on this issue of why final 
    public void update() 
    { 
     // Called by one thread constantly 
     variable.getAndIncrement(); // atomically adds one 
    } 
    public int retrieveValue() 
    { 
     return variable.get(); // gets the current int value safely 
    } 
} 

public class B 
{ 
    public A a; 
    public void update() 
    { 
     // Called by another thread constantly 
     int v = a.retrieveValue(); 
     // Do algorithm with v... 
    } 
} 

अधिक जटिल एल्गोरिदम के लिए, जैसा कि आपका हालिया संपादन मानता है, सिंक्रनाइज़ेशन या ताले का उपयोग करें।

+0

"कुछ प्रकार का लॉक" कहकर, आपका मतलब है "इसे सिंक्रनाइज़ किए गए ब्लॉक में डालें या विधि सिंक्रनाइज़ करें " है न ? इसके अलावा, परमाणु इंटेगर – Riduidel

+0

के साथ +1 या किसी प्रकार के 'java.util.concurrent.Lock' का उपयोग करें। मैं अधिक अभिव्यक्ति के लिए 'सिंक्रनाइज़' पर अधिक पसंद करता हूं - मुझे विशेष रूप से 'रीडवाइट लॉक' पसंद है। – justkt

+2

आपकी टिप्पणी "अस्थिर इसे प्रभावित नहीं करेगा, यह एक आदिम नहीं है" भ्रामक है। इसके साथ कोई लेना-देना नहीं है कि यह क्षेत्र एक मूलभूत है, लेकिन इस तथ्य के साथ सब कुछ करने के लिए कि 'परिवर्तनीय' को फिर से असाइन नहीं किया जा रहा है। 'वेरिएबल' फाइनल बनाना यहां सलाह दी जाएगी। –

9

इस मामले में मैं AtomicInteger का उपयोग करूंगा, हालांकि सामान्यीकृत उत्तर यह है कि परिवर्तनीय तक पहुंच को सिंक्रनाइज़ किए गए ब्लॉक द्वारा संरक्षित किया जाना चाहिए, या java.util.concurrent पैकेज के किसी अन्य भाग का उपयोग करके।

उदाहरण के एक जोड़े:

सिंक्रनाइज़ का उपयोग कर

public class A { 
    public final Object variable; 
    public void update() { 
     synchronized(variable) { 
      variable.complexAlgorithm(); 
     } 
    } 
} 

public class B { 
    public A a; 
    public void update() { 
     sychronized(a.variable) { 
      consume(a.variable); 
     } 
    } 
} 

पहुँच java.util.concurrent

public class A { 
    public final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 
    public final Object variable; 
    public void update() { 
     lock.writeLock().lock(); 
     try { 
      variable.complexAlgorithm(); 
     } finally { 
      lock.writeLock().unlock(); 
     } 
    } 
} 

public class B { 
    public A a; 
    public void update() { 
     a.lock.readLock().lock(); 
     try { 
      consume(a.variable); 
     } finally { 
      a.lock.readLock().unlock(); 
     } 
    } 
} 
+0

क्या आप समझा सकते हैं कि क्लास ए में variable.getWriteLock() लॉक() क्यों नहीं है? – Radu

+0

आप केवल किसी ऑब्जेक्ट पर सिंक्रनाइज़ कर सकते हैं, और उस ऑब्जेक्ट को अंतिम होने की आवश्यकता है। इस उदाहरण में, सिंक्रनाइज़ेशन ReadWriteLock के कार्यान्वयन के माध्यम से किया जाता है (इसलिए एकाधिक धागे समवर्ती रूप से पढ़ सकते हैं) - http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock देखें .html –

4

का उपयोग उपयोग AtomicInteger या synchronize सुरक्षित है।

+0

क्या आप कृपया समझा सकते हैं कि सिंक्रनाइज़ करके आपका क्या मतलब है? यह कहां जाना चाहिए, यह मेरे लिए एक उलझन में है। – Dave

+0

@ डेव - http://download.oracle.com/javase/tutorial/essential/concurrency/sync.html आपको मूल जावा सिंक्रनाइज़ेशन के साथ मदद करनी चाहिए। – justkt

संबंधित मुद्दे