2012-12-06 28 views
9

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

लेकिन जावा में इसे कैसे कार्यान्वित करें? स्पष्ट रूप से "रिलीज" लॉक कैसे करें? लॉक के लिए प्रतीक्षा करने के लिए टाइमआउट को कैसे परिभाषित करें।

सटीक जावा आदेश और वाक्यविन्यास क्या है। कृपया कोई हैलो-सांसारिक उदाहरण कृपया?

+2

अन्य समाधान; हमेशा एक ही क्रम में ताले हासिल करते हैं, या एक से अधिक ताला कभी हासिल नहीं करते हैं। ;) –

+0

'लॉक के लिए प्रतीक्षा करने के लिए टाइमआउट को परिभाषित करने के लिए कैसे करें' – n611x007

उत्तर

8

यहाँ 2 ताले और 2 धागे कि उन्हें विभिन्न क्रम में पाने की कोशिश के साथ एक काल्पनिक उदाहरण है। टाइमआउट के बिना, कोड डेडलॉक होगा।

public static void main(String[] args) throws Exception { 
    final ReentrantLock lock1 = new ReentrantLock(); 
    final ReentrantLock lock2 = new ReentrantLock(); 
    Runnable try1_2 = getRunnable(lock1, "lock 1", lock2, "lock 2"); 
    Runnable try2_1 = getRunnable(lock2, "lock 2", lock1, "lock 1"); 
    new Thread(try1_2).start(); 
    new Thread(try2_1).start(); 
} 

private static Runnable getRunnable(final ReentrantLock lock1, final String lock1Name, final ReentrantLock lock2, final String lock2Name) { 
    return new Runnable() { 
     @Override 
     public void run() { 
      try { 
       if (lock1.tryLock(1, TimeUnit.SECONDS)) { 
        System.out.println(lock1Name + " acquired in thread " + Thread.currentThread()); 
        if (lock2.tryLock(1, TimeUnit.SECONDS)) { 
         System.out.println(lock2Name + " acquired in thread " + Thread.currentThread()); 
         Thread.sleep(2000); 
        } else { 
         System.out.println("Could not acquire "+lock2Name + " in thread " + Thread.currentThread()); 
         lock1.unlock(); 
         System.out.println(lock1Name + " released in thread " + Thread.currentThread()); 
        } 
       } else { 
        System.out.println("Could not acquire " + lock1Name + " in thread " + Thread.currentThread()); 
       } 
      } catch (InterruptedException e) { 
       //you should not ignore it 
      } finally { 
       if (lock1.isHeldByCurrentThread()) lock1.unlock(); 
       if (lock2.isHeldByCurrentThread()) lock2.unlock(); 
      } 
     } 
    }; 
} 
+1

अभ्यास में जावा कंसुरेंसी से उदाहरण !! ;) –

+1

@assylias किसी ऑब्जेक्ट की सिंक्रनाइज़ विधि को कॉल करते समय, थ्रेड स्वचालित रूप से "उस ऑब्जेक्ट को लॉक" करने का प्रयास करता है। जबकि "java.util.concurrent.locks.Lock" का उपयोग करते समय हम "ऑब्जेक्ट ऑब्जेक्ट पर लॉक करें" का अनुरोध नहीं करेंगे जिसका तरीका हम कॉल कर रहे हैं।तो मुझे लगता है कि, "लॉक" कक्षा का सही ढंग से उपयोग करने के लिए हमें सिंक्रनाइज़ के रूप में विधि को चिह्नित नहीं करना चाहिए। लेकिन हमारे पास उस ऑब्जेक्ट के साथ "लॉक" का आवंटन होना चाहिए। और कोड को कॉल करने से पहले - जिसे सिंक्रनाइज़ेशन की आवश्यकता होती है- हमें संबंधित लॉक पर tryLock() के लिए जाना चाहिए। ---- कृपया नीचे टिप्पणी पढ़ना जारी रखें ------ –

+0

@assylias इसलिए हम उस ऑब्जेक्ट को भौतिक रूप से लॉक नहीं कर रहे हैं जिसकी विधि हम कॉल कर रहे हैं, लेकिन तार्किक रूप से लॉकिंग। जैसा कि हमारे पास प्रत्येक ऑब्जेक्ट के लिए एक बाल्कबोर्ड है और कॉलिंग विधि से पहले हम केवल ब्लैकबॉर्ड पर लिखते हैं कि "अरे, मुझे लॉक मिल गया है !!" । हम वास्तव में वस्तु को लॉक नहीं करते हैं। अन्य धागा ब्लैकबोर्ड की जांच करेगा और देखें कि किसी ने "कहा" है कि उसके पास लॉक है। तो यह जारी नहीं रहेगा। क्या मैं सही हूँ? –

3

Lock in Java

Use tryLock(timeout, timeunits); 

ताला का अधिग्रहण अगर यह मुक्त दिया के भीतर समय इंतजार कर और वर्तमान धागा बाधित नहीं किया गया है। यदि लॉक उपलब्ध है विधि के साथ तुरंत देता है।

तो ताला उपलब्ध नहीं है तो मौजूदा धागा धागा शेड्यूलिंग प्रयोजनों के लिए विकलांग हो जाता है और निष्क्रिय झूठ जब तक तीन बातों में से एक होता है:

ताला वर्तमान धागा ने अधिग्रहण कर लिया है;

या कुछ अन्य धागा बीच में आता है वर्तमान धागा, और लॉक अधिग्रहण की रुकावट समर्थित है;

या निर्दिष्ट इंतज़ार कर समय समाप्त होने

3

हो सकता है इस मदद,

Lock lock = null; 
lock=....; 
if (lock.tryLock(15L, TimeUnit.SECONDS)) { 
    try { 
     ........ 
    } finally { 
     lock.unlock(); 
    } 
} else { 
     // do sumthing 
} 
0

में Java 8+ Concurrency API आप जब यह हालत सेट कर दिया जाता है प्रतीक्षा करने के लिए एक lock के लिए एक स्पष्ट समय निर्धारित कर सकते हैं:

private Lock lock = new ReentrantLock(); 
private Condition myCondition = lock.newCondition(); 

try{    
    myCondition.await(1200L, TimeUnit.MILLISECONDS); 
} catch (InterruptedException e) { 
    System.out.println((e); 
} finally{ 
    lock.unlock(); 
} 

ताला जब तक यह एक और धागे से या जब तक एक signal() या signalAll() प्राप्त करता है इंतजार करेंगे 1.2 सेकंड का समय समाप्त हो जाता है।