2013-06-20 6 views
7

जावा ऑब्जेक्ट के लिए बताने का कोई तरीका है, जो थ्रेड (या नल) वर्तमान में इसके मॉनीटर का मालिक है? या कम से कम एक तरीका यह बताने के लिए कि क्या मौजूदा धागे का मालिक है?निर्धारित करें कि कौन सा धागा मॉनीटर का मालिक है

+0

आप इस जानकारी को पाने के लिए थ्रेड डंप कर सकते हैं – fge

उत्तर

9

मुझे कुछ जवाब मिल गए हैं। परीक्षण करने के लिए कि क्या मौजूदा थ्रेड मॉनिटर रखता है, Thread.holdsLock मौजूद है!

if (!Thread.holdsLock(data)) { 
    throw new RuntimeException(); // complain 
} 

यह वास्तव में तेज़ (उप-माइक्रोसॉन्ड) है और 1.4 के बाद से उपलब्ध है।

सामान्य रूप से परीक्षण करने के लिए, कौन सा थ्रेड (या थ्रेड आईडी) लॉक रखता है, java.lang.management कक्षाओं (धन्यवाद @amicngh) के साथ ऐसा करना संभव है।

public static long getMonitorOwner(Object obj) { 
    if (Thread.holdsLock(obj)) return Thread.currentThread().getId(); 
    for (java.lang.management.ThreadInfo ti : 
      java.lang.management.ManagementFactory.getThreadMXBean() 
      .dumpAllThreads(true, false)) { 
     for (java.lang.management.MonitorInfo mi : ti.getLockedMonitors()) { 
      if (mi.getIdentityHashCode() == System.identityHashCode(obj)) { 
       return ti.getThreadId(); 
      } 
     } 
    } 
    return 0; 
} 

इस के साथ कुछ चेतावनियां नहीं है:

  1. यह थोड़ा धीमा (~ साढ़े मेरे मामले में मिलीसेकंड और शायद धागे की संख्या के साथ रैखिक बढ़ जाती है) है।
  2. इसके लिए जावा 1.6 और एक वीएम की आवश्यकता है जिसके लिए ThreadMXBean.isObjectMonitorUsageSupported() सत्य है, इसलिए यह कम पोर्टेबल है।
  3. इसे "मॉनीटर" सुरक्षा अनुमति की आवश्यकता है, इसलिए संभावित रूप से एक सैंडबॉक्स वाले एप्लेट से काम नहीं करेगा।
  4. थ्रेड आईडी को थ्रेड ऑब्जेक्ट में बदलना, यदि आपको आवश्यकता है, तो थोड़ा गैर-तुच्छ है, क्योंकि मुझे लगता है कि आपको थ्रेड.इन्यूमेरेट का उपयोग करना होगा और फिर यह पता लगाने के लिए कि किसके पास आईडी है, लेकिन लूप इसमें सैद्धांतिक दौड़ की स्थिति है क्योंकि जब तक आप गणना करते हैं, तब तक यह धागा मौजूद नहीं हो सकता है, या एक नया धागा दिखाई दे सकता है जिसमें एक ही आईडी है।

लेकिन यदि आप केवल वर्तमान धागे का परीक्षण करना चाहते हैं, तो Thread.holdsLock बहुत अच्छा काम करता है! अन्यथा, java.util.concurrent.locks.Lock के कार्यान्वयन सामान्य जावा मॉनीटर (धन्यवाद @ user1252434) से अधिक जानकारी और लचीलापन प्रदान कर सकते हैं।

2

जावा क्लास मॉनीटर जेवीएम के लिए आंतरिक है और आप वास्तव में इसके साथ नहीं खेल सकते हैं।

यदि आप जानते हैं कि ऑब्जेक्ट लॉक है, तो आप मॉनिटर को फिर से प्राप्त करने का प्रयास कर सकते हैं - अगर आप इसे प्राप्त कर सकते हैं, तो इसका मतलब है कि आप ऑब्जेक्ट को अपने थ्रेड से लॉक कर रहे हैं (क्योंकि जावा लॉक रिकर्सिव हैं - आप लॉक कर सकते हैं एक ही धागे से दो बार)। समस्या यह है कि आप सिंक्रनाइज़ करने के लिए को आजमा सकते हैं।

आप असुर ऑब्जेक्ट का उपयोग कर सकते हैं। असुरक्षित में tryMonintorEnter() विधि है जो बस यही करती है। unsafe देखें।

असुरक्षित वास्तव में मदद करने के लिए आप धागा कि मॉनिटर रखती पाने में सक्षम हो सकता है, लेकिन मुझे लगता है कि ऐसा करने के लिए पता नहीं कैसे ...

1

में जावा 1.6 आप प्रतिबिंब का उपयोग कर सकते यह जानकारी प्राप्त करने ।

ThreadMXBean tBean = ManagementFactory.getThreadMXBean(); 
ThreadInfo[] threadInfo = tBean .getThreadInfo(bean.getAllThreadIds(), true, true); 
1

इसके बजाय synchronized का उपयोग कर के, आप, ReentrantLock पर एक नज़र डालें करना चाह सकते हैं विशेष रूप से अपने तरीकों getOwner() और isHeldByCurrentThread()। हालांकि, इसका उपयोग करने के लिए थोड़ा और अनुशासन होता है, क्योंकि आपको स्पष्ट रूप से unlock() होना चाहिए, प्राथमिक रूप से finally ब्लॉक में।

+0

मैं RentrantLock से परिचित नहीं था। हालांकि यह मेरा सवाल नहीं था, मुझे लगता है कि यह मेरे उपयोग के मामले में वास्तव में बेहतर है, क्योंकि मैं कक्षा सी में लॉकिंग कर सकता हूं और कॉल के बीच लॉक को बनाए रख सकता हूं। बहुत बहुत धन्यवाद। – Boann

+0

यदि आप चाहें तो आप अपना लॉकिंग तर्क रख सकते हैं। ReentrantLock का उपयोग करने के लिए एकमात्र आवश्यक परिवर्तन 'सिंक्रनाइज़ (myLock) {..} 'myLock.lock() से है; {..} अंत में {myLock.unlock();} 'कोशिश करें। हालांकि, सिंक्रनाइज़ करने के विपरीत लॉक केवल कोई ऑब्जेक्ट नहीं हो सकता है। – user1252434

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