2012-11-15 2 views
9

तो मैं भले ही objectTwo के लिए ताला उपलब्ध है इसजावा में बाधाओं के आदेश के बिना एकाधिक ताले कैसे प्राप्त करें?

synchronized(objectOne){ do stuff } 
synchronized(objectTwo){ do stuff } 

इस के साथ समस्या यह कार्यक्रम पर ताला के लिए इंतजार करेंगे है के समान कोड है,। मैं जो करने की कोशिश कर रहा हूं वह कहता है: और objectTwo दोनों को लॉक करने का प्रयास करें, और जो भी लॉक आपको पहले लॉक करता है वह उस लॉक के लिए सामान करता है। मैं एक समाधान के साथ आया हूं लेकिन मुझे लगता है कि यह बदसूरत है और मैं सोच रहा हूं कि किसी के पास कोई बेहतर विचार है या नहीं।

यहां मेरा विचार है: 2 धागे शुरू करें, प्रत्येक लॉक पर प्रतीक्षा कर रहा है और फिर मुख्य धागा CountDownLatch पर प्रतीक्षा करेगा। तो अगर आप कुछ इस तरह के साथ अंत:

CountDownLatch latch = new CountDownLatch(2); 

new Thread(new Runnable(){ 
public void run(){ 
    synchronized(objectOne) { do stuff } 
    latch.countDown(); 
}).start(); 

new Thread(new Runnable(){ 
public void run(){ 
    synchronized(objectTwo) { do stuff } 
    latch.countDown(); 
}).start(); 

latch.await(); 
+1

यह मेरे लिए एक उचित दृष्टिकोण की तरह लगता है। – ArtB

+0

मैं पोस्ट किए गए कोड से नहीं बता सकता, लेकिन मेरे अनुभव में, एक वर्ग जो दो अलग-अलग वस्तुओं पर ताला लगाता है, लगभग हमेशा दो वर्गों में विभाजित होना चाहिए, लॉकिंग के साथ ** दो कक्षाओं के अंदर ** कक्षा के अनुसार नहीं उन्हें – Nate

+0

आप दो अलग-अलग ताले का उपयोग कर रहे हैं, इसलिए थ्रेड बी को थ्रेड ए द्वारा मेमोरी में बदलाव नहीं दिखाई दे सकते हैं, मुझे संदेह है कि यहां कोई घटना नहीं होगी-इससे पहले। –

उत्तर

5

मुझे लगता है कि आप Lock जो आप विधि boolean tryLock() साथ प्रदान करता है का उपयोग करना चाहिए।

रिटर्न: सच अगर ताला हासिल कर लिया और झूठी था अन्यथा

के साथ आगे बढ़ें जब आप ताले कम से कम एक है सामान है।

+0

तो क्या आप कुछ ताले की कोशिश करते हुए बार-बार कोशिश कर रहे हैं जब तक आप किसी एक को प्राप्त न करें, कुछ व्यस्त प्रतीक्षा लूप द्वारा encapsulated? – user1825426

2

हो सकता है कि आप 2 कतारों की नौकरियां, 2 धागे प्रत्येक कतार में मतदान कर सकें और नौकरियां निष्पादित कर सकें।

ऑब्जेक्ट से संबंधित नौकरियों के लिए, आप इसे कतार # 1 में डाल देते हैं; ऑब्जेक्ट से संबंधित नौकरियां कतार # 2 में दो।

worker1.queue.put(new Runnable(){ public void run() { do stuff } }); 
worker2.queue.put(new Runnable(){ public void run() { do stuff } }); 

---- 

class Worker extends Thread 

    BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(); 

    public void run() 
     while(true) 
      queue.take().run(); 
0

stuff की राशि पर निर्भर करता है यह काम करना एक से अधिक थ्रेड बंद स्पिन के लिए और अधिक भूमि के ऊपर हो सकता है। stuff एक तेज़ पर्याप्त ऑपरेशन है, तो यह एक थ्रेड में सामान करना सबसे अच्छा हो सकता है। आपको इसे जानने के लिए समय लेना होगा।

0

मैं आपके हैक की तरह, कम से कम अगर यह एक बंद स्थिति है। उस ने कहा ...

यदि आप इस तरह की चीज कर रहे हैं और कुछ "कम हैकी" चाहते हैं, तो मैं ExecutorService#invokeAll() का सुझाव दूंगा। यह कॉलबल्स की एक सूची लेता है, उन्हें थ्रेड पूल और ब्लॉक पर निष्पादित करता है जब तक कि वे सब कुछ नहीं किया जाता है।

स्केच:

ExecutorService es = Executors.newCachedThreadPool(); // for example... 
List<Future<Void>> results = es.invokeAll(new ArrayList {{ 
     add(new Callable<Void> { 
      public Void call() { synchronized(objectOne) { do stuff } } 
     }); 
     add(new Callable<Void> { 
      public Void call() { synchronized(objectTwo) { do stuff } } 
     }); 
    }}); 
// both Callables are done when you get here 

यह स्पष्ट रूप से मान लिया गया है कि यह अपने अनुप्रयोग में इस बिंदु पर अलग धागे से इन तरीकों कॉल करने के लिए ठीक है। अगर किसी कारण से आपको दोनों को एक ही थ्रेड से कॉल करने की आवश्यकता है, तो मुझे लगता है कि आप tryLock का उपयोग करने के लिए बर्बाद हो गए हैं और व्यस्त गुरु के जवाब में चर्चा के रूप में व्यस्त प्रतीक्षा करें।

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