2010-07-13 13 views
7

मैंने कल कुछ अजीब देखा है। ऐसा लगता है कि दो धागे एक ही समय में एक ही ऑब्जेक्ट पर लॉकिंग दो सिंक्रनाइज़ किए गए ब्लॉक दर्ज कर रहे हैं।सिंक्रनाइज़ अनुभाग ब्लॉक नहीं करता है!

वर्ग (MyClass) प्रासंगिक कोड युक्त इस जैसा दिखता है:

private static int[] myLock = new int[0]; 

protected static int methodA(final long handle, final byte[] sort) { 
    synchronized (myLock) { 
     return xsMethodA(handle, sort); 
    } 
} 

protected static int methodB(final long handle) { 
    synchronized (myLock) { 
     return xsMethodB(handle); 
    } 
} 

मैं अपने आवेदन ऊपर वर्ग चलाने का एक धागा डंप बनाया और बहुत हैरान था के रूप में मैं इसे देखा:

"http-8080-136" daemon prio=10 tid=0x00000000447df000 nid=0x70ed waiting for monitor entry [0x00007fd862aea000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
    at com.MyClass.methodA(MyClass.java:750) 
    - locked <0x00007fd8a6b8c790> (a [I) 
    at com.SomeOtherClass.otherMethod(SomeOtherClass.java:226) 
    ... 

"http-8080-111" daemon prio=10 tid=0x00007fd87d1a0000 nid=0x70c8 waiting for monitor entry [0x00007fd86e15f000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
    at com.MyClass.methodB(MyClass.java:991) 
    - locked <0x00007fd8a6b8c790> (a [I) 
    at com.SomeOtherClass.yetAnotherMethod(SomeOtherClass.java:3231) 
    ... 

(मैं सादगी के मामले के लिए वर्ग और विधि के नाम बदल गया है, तो मूर्खतापूर्ण नाम से उलझन में नहीं मिलता।)

ऐसा नहीं है कि thr लगता है ईएडी http-8080-136 और http-8080-111 दोनों ने myLock पर लॉक हासिल किया है। यह वही वस्तु है क्योंकि ऑब्जेक्ट पता समान है: 0x00007fd8a6b8c790। जावा रनटाइम विशिष्टता synchronized कीवर्ड के बारे में इस का कहना है:

एक सिंक्रनाइज़ बयान को क्रियान्वित धागा की ओर से एक आपसी-बहिष्कार ताला (§17.1) का अधिग्रहण एक ब्लॉक को निष्पादित करता है, तो अवरोध समाप्त। जबकि निष्पादन थ्रेड लॉक का मालिक है, कोई अन्य थ्रेड लॉक प्राप्त कर सकता है। [The Java Language Specification, 14.19]

तो यह कैसे संभव है?

लॉक के लिए थ्रेड डंप "प्रतीक्षा" में एक और 44 धागे हैं। ऐसा लगता है कि धागा इंतजार कर रहा है:

"http-8080-146" daemon prio=10 tid=0x00007fd786dab000 nid=0x184b waiting for monitor entry [0x00007fd8393b6000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
    at com.MyClass.methodC(MyClass.java:750) 
    - waiting to lock <0x00007fd8a6b8c790> (a [I) 
    at com.SomeOtherClass.yetAnoterMethod2(SomeOtherClass.java:226) 

उत्तर

4

मैं हॉटस्पॉट-देव मेलिंग सूची पर एक ही प्रश्न पूछा और क्रिस्टोफर फिलिप्स से एक बहुत ही goot जवाब प्राप्त किया है:


हाय एडवर्ड

मुझे लगता है कि अपने धागा डंप कि भ्रामक है ।

यदि आप वास्तव में सोचते हैं कि 2 लॉक में एक साथ हैं तो आपको शायद एक गकोर (जो बाहरी रूप से संगत है) प्राप्त करना चाहिए। (भी osThread.hpp में OSThreadContendState देखें) से कहा जाता है: src/शेयर/VM

राज्य आप "पर नजर रखने के प्रवेश के लिए इंतजार कर" देख वास्तव में MONITOR_WAIT जो एक गर्म ताला की वास्तविक अधिग्रहण से पहले निम्न कोड का प्रतिनिधित्व कर सकते है/क्रम/सिन्क्रोनाइज़र।सीपीपी

3413  OSThreadContendState osts(Self->osthread()); 
3414  ThreadBlockInVM tbivm(jt); 
3415 
3416  Self->set_current_pending_monitor(this); 
3417 
3418  // TODO-FIXME: change the following for(;;) loop to straight-line code. 
3419  for (;;) { 
3420  jt->set_suspend_equivalent(); 
3421  // cleared by handle_special_suspend_equivalent_condition() 
3422  // or java_suspend_self() 
3423 
3424  EnterI (THREAD) ; 
3425 
3426  if (!ExitSuspendEquivalent(jt)) break ; 
3427 
3428  // 
3429  // We have acquired the contended monitor, but while we were 
3430  // waiting another thread suspended us. We don't want to enter 
3431  // the monitor while suspended because that would surprise the 
3432  // thread that suspended us. 

क्रिस

1

थ्रेड डंप कैसे लिया गया था? यदि धागे को रोका नहीं गया था तो लॉक स्वामित्व एक थ्रेड और अगले डंपिंग के बीच बदल सकता था।

+0

प्रक्रिया के लिए संकेत QUIT भेज कर। मुझे नहीं पता कि सूर्य वीएम थ्रेड डंप के दौरान कैसे कार्य करता है। लेकिन मुझे लगता है कि प्रक्रिया रुक गई है। अन्यथा आप एक असंगत थ्रेड डंप प्राप्त करेंगे। –

+0

मुझे आईबीएम जेवीएम के लिए पता है यह जरूरी नहीं है, सूर्य के बारे में निश्चित नहीं है, हालांकि, निश्चित रूप से कुछ ध्यान में रखना है। –

+0

यह साइट दावा करती है कि सभी धागे रोक दिए गए हैं: http://expertodev.wordpress.com/2009/05/30/how-to-take-java-thread-dump/ –

0

मुझे लगता है कि प्रासंगिक जानकारी है: "मॉनीटर एंट्री के लिए प्रतीक्षा", जो दोनों धागे के लिए समान है। चूंकि दोनों धागे (थ्रेड डंप में) को डेमॉन धागे चिह्नित किया जाता है, मुझे लगता है कि एक ही समय में एक मुख्य थ्रेड चलाना भी चाहिए। क्या यह संभव है कि मुख्य थ्रेड वर्तमान मॉनिटर मालिक है जो अन्य दो धागे को अवरुद्ध करता है?

+0

नहीं, मुख्य धागा कुछ भी नहीं करता है। यहां तक ​​कि यदि मुख्य धागा ताला पकड़ लेता है, तो विनिर्देश मुख्य और डीमॉन धागे के बीच अंतर नहीं करता है। लॉक के मालिक होने के लिए केवल एक थ्रेड की अनुमति है। –

+0

मैं मानता हूं, लॉक प्राप्त करने और महत्वपूर्ण अनुभाग (विनिर्देश के अनुसार) में प्रवेश करने के लिए केवल एक थ्रेड की अनुमति है। थ्रेड डंप में बताए गए अनुसार, दोनों डेमॉन-थ्रेड लॉक के लिए * प्रतीक्षा * हैं। क्या आप वाकई लॉक धारण करने वाले कोई अन्य धागा नहीं हैं? – Javaguru

+0

दो धागे http-8080-136 और http-8080-111 लॉक धारण कर रहे हैं। लॉक के लिए थ्रेड डंप "प्रतीक्षा" में एक और 44 धागे हैं। –

0

उन्होंने लॉक हासिल नहीं किया है, अन्यथा आप एक stacktrace में xsMethodA या xsMethodB देखेंगे।

+0

तो थ्रेड http-8080-111 और http-8080-146 के बीच कोई अंतर क्यों है? –

+0

और: ThreadDumpAnalyzer दोनों धागे (http-8080-136, http-8080-111) को "लॉक द्वारा" के रूप में सूचीबद्ध करता है। –

+0

मेरा मतलब है कि "सिंक्रनाइज़ किया गया ब्लॉक" शीर्षक गलत है। हो सकता है कि आपका मतलब हो "ब्लॉक लॉक होने पर सिंक्रनाइज़ ब्लॉक ब्लॉक"? –

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