6

यहाँ कोड मैं भर में ठोकर खाई है:थ्रेडलोकल पर संचालन सिंक्रनाइज़ किया जाना है?

class TransactionContextHolder { 

private static final ThreadLocal<TransactionContext> currentTransactionContext = new NamedInheritableThreadLocal<TransactionContext>(
    "Test Transaction Context"); 


static TransactionContext getCurrentTransactionContext() { 
    return currentTransactionContext.get(); 
} 

static void setCurrentTransactionContext(TransactionContext transactionContext) { 
    currentTransactionContext.set(transactionContext); 
} 

static TransactionContext removeCurrentTransactionContext() { 
    synchronized (currentTransactionContext) { 
     TransactionContext transactionContext = currentTransactionContext.get(); 
     currentTransactionContext.remove(); 
     return transactionContext; 
    } 
} 

}

currentTransactionContext फ़ील्ड प्रकार ThreadLocal की है और यह कक्षा में केवल क्षेत्र है।

ऐसा लगता है कि सिंक्रनाइज़ेशन की आवश्यकता नहीं है क्योंकि थ्रेडलोकल में संग्रहीत मान विशेष थ्रेड से जुड़ा हुआ है और इस प्रकार यह एक साझा स्थिति नहीं है। इसके अलावा मुझे लगता है कि यह प्रदर्शन को प्रभावित करता है क्योंकि वर्तमान ट्रांज़ेक्शन कॉन्टेक्स्ट स्वयं साझा किया जाता है और ब्लॉक में प्रवेश करने के लिए केवल एक थ्रेड को अनुमति दी जाती है जबकि कई लोग समानता को प्रभावित किए बिना समानांतर में कर सकते हैं।

क्या सिंक्रनाइज़ेशन की आवश्यकता है?

+1

बस सुनिश्चित करें कि 'currentTransactionContext.initialValue' (या यहां तक ​​गेटर) एक साझा राज्य नहीं है हो सकता है और उसके बाद आप होना चाहिए सिंक्रनाइज़ेशन को हटाने के साथ ठीक है। –

उत्तर

6

सामान्य में, यह, की गारंटी देता है केवल एक कार्यक्रम के एक छोटे स्निपेट प्रदान threadsafety के बारे में करना मुश्किल है के बाद से threadsafety पूरे कार्यक्रम की संपत्ति है, और synchronized एक कार्यक्रम के कई अलग अलग हिस्सों में व्यवहार समन्वय कर सकते हैं।

उदाहरण के लिए: शायद कहीं और कोड का कोई अन्य टुकड़ा है जो थ्रेडलोकल के गले का निरीक्षण करने और/या उत्परिवर्तित करने की कोशिश करने के लिए पागल असुरक्षित प्रतिबिंब का उपयोग करता है, और इसलिए यदि आप थ्रेडलोकल को लॉक किए बिना बदल देते हैं तो वह तोड़ देगा?

यथार्थवादी, हालांकि, आप बिल्कुल सही हैं: शायद initialValue विधि के अंदर, थ्रेडलोकल इंस्टेंस पर सिंक्रनाइज़ करने का कोई कारण नहीं है। थ्रेडलोकल स्वयं ही एक थ्रेडस्फीटी तंत्र है, और यह synchronized पर किसी भी तरह से निपटने से आपके थ्रेडसाफ्टी को बेहतर तरीके से प्रबंधित करता है।

(initialValue मामले ओर इशारा करते हुए के लिए Margaret Bloom को टोपी की नोक।)

+0

बिल्कुल। दौड़ की स्थिति का एकमात्र स्रोत मैं सोच सकता हूं कि विधि ['प्रारंभिक वैल्यू'] है (https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html#initialValue()) 'ThreadLocal'। यह सभी धागे में साझा किया जाता है और जैसा कि दस्तावेज़ से जुड़े उदाहरण में देखा गया है, इसे कुछ सुरक्षा का उपयोग करना चाहिए। इस विधि को 'get'' कहा जाता है क्योंकि वे हमेशा इसके बाद 'हटाएं' करते हैं (पता नहीं क्यों) –

+0

@MargaretBloom: पुन: "वे हमेशा इसके बाद 'हटाएं' निष्पादित करते हैं (क्यों नहीं जानते)": खैर, ओपी पोस्ट किया गया क्या है 'removeCurrentTransactionContext' विधि, इसलिए मुझे लगता है कि यह समझ में आता है कि यह हमेशा मौजूदा लेनदेन संदर्भ को हटा देता है। – ruakh

+0

ठीक है, मैंने विधि नाम को अनदेखा किया है :) 'निकालना' समझ में आता है, यह 'get' है जो संदिग्ध है। यदि अभी तक कोई संदर्भ नहीं है, तो वह विधि संभावित रूप से एक नया बना सकती है और फिर इसे हटा सकती है। लेकिन जैसा कि आपने कहा था: यह केवल एक छोटा सा स्निपेट है। –

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