2009-11-22 9 views
14

जावा में, असाइनमेंट परमाणु है यदि चर का आकार 32 बिट्स से कम या बराबर है लेकिन 32 बिट से अधिक नहीं है।आदिम प्रकार के लिए अस्थिर या सिंक्रनाइज़?

क्या (अस्थिर/सिंक्रनाइज़) डबल या लंबी असाइनमेंट के मामले में उपयोग करने के लिए अधिक कुशल होगा?

की तरह,

volatile double x = y; 

सिंक्रनाइज़ आदिम तर्क के साथ लागू नहीं है। मैं इस मामले में सिंक्रनाइज़ का उपयोग कैसे करूं? बेशक मैं अपनी कक्षा को लॉक नहीं करना चाहता, इसलिए this का उपयोग नहीं किया जाना चाहिए।

+0

आप "अपनी [कक्षा] लॉक क्यों नहीं करना चाहते"? (ध्यान दें कि किसी इंस्टेंस विधि पर लॉक केवल ऑब्जेक्ट पर ही लिया जाता है)। ध्यान दें कि आधुनिक जेवीएम बेहद उन्नत हैं और सिंक्रनाइज़ेशन का प्रदर्शन ओवरहेड आमतौर पर कोई समस्या नहीं है –

+0

मेरे पास एक jsp है जहां कई लोग डेटा एक्सेस/अपडेट करते हैं। डेटा एक कैश ऑब्जेक्ट में है और वहां मुझे इन सिंक्रनाइज़ेशन और एट अल की आवश्यकता है क्योंकि लोगों की संख्या कई हो सकती है। – DKSRathore

+1

मुझे लगता है कि मुझे एओमिक डबल के साथ जाना चाहिए। – DKSRathore

उत्तर

5

के सेटटर/गेटर में सिंक्रनाइज़ करते हैं यदि आपको ऑब्जेक्ट पर लॉकिंग बहुत भारी लगता है, तो सिंक्रनाइज़ करने का तरीका है। जावा 1.5 अस्थिरता से पहले एक अच्छा विकल्प हो सकता है, लेकिन अब अस्थिरता उस विधि पर निर्देश ऑर्डर करने के लिए बहुत बड़ा प्रभाव डाल सकती है जहां असाइनमेंट होता है। एक अलग ऑब्जेक्ट बनाएं (private final Object X_LOCK = new Object();) और उस डबल के मान को सेट या प्राप्त करते समय उस पर सिंक्रनाइज़ करें। यह आपको लॉकिंग पर नियंत्रण का एक अच्छा स्तर देगा, जो ऐसा लगता है कि आपको इसकी आवश्यकता है।

नए समवर्ती पैकेज में अधिक विकल्प हैं, जैसे परमाणु संदर्भ जो अस्थिरता के लिए एक अच्छा प्रतिस्थापन हो सकता है यदि आपको वास्तव में सिंक्रनाइज़ेशन से बचने की आवश्यकता है।

+1

क्या आप कह रहे हैं कि 'अस्थिर' कम प्रदर्शनकारी है? – Pacerier

+0

@Pacerier, यह वास्तव में निर्भर करता है (@oxbow_lakes प्रदर्शन बिंदु को काफी अच्छी तरह से हिट करता है), लेकिन इसका उपयोग अब से अधिक प्रभाव (1.5 और अधिक के साथ) होता है, और यह अधिक सरल होना संभव है। व्यावहारिक रूप से, इस मामले में बहुत से विवाद और निर्देशों के पुन: क्रम के लिए अच्छे अवसरों के साथ कुछ बहुत भारी इस्तेमाल किया जाना होगा। इसलिए यह सबूत के बिना एक सार्थक प्रदर्शन अनुकूलन नहीं है जो आपके विशिष्ट मामले में एक समस्या है (वास्तव में बहुत कम चीजें हैं)। – Yishai

+1

किसी ऑब्जेक्ट पर सिंक्रनाइज़ करना वही होता है-अर्थात् ऑर्डर करने से पहले। – eckes

26

आप क्या करने की कोशिश कर रहे हैं? synchronized और volatile कीवर्ड जावा में तंत्र हैं जिनका उपयोग यह सुनिश्चित करने के लिए किया जा सकता है कि एक ही डेटा को पढ़ने वाले विभिन्न धागे द्वारा लगातार मूल्यों को देखा जा सके। विशेष रूप से वे आपको के कारण होने की अनुमति देते हैं- आपके कार्यक्रमों में संबंधों से पहले।

आप बस ताकि ठीक से एक मल्टी-थ्रेडेड कार्यक्रम में गैर final क्षेत्रों तक पहुँचने के लिए में volatile या synchronized से एक का उपयोग करने से बचने नहीं कर सकते। उस ने कहा, मुख्य कारण यह है कि आपको volatile परमाणु का उपयोग करने की आवश्यकता है और संचालन (यानी सेट करें) यह पर कोई प्रदर्शन विचार नहीं होगा)। उदाहरण के लिए, एक मल्टी-थ्रेडेड कार्यक्रम में:

volatile int i = 0; 

public void foo() { 
    if (i == 0) i = i + 1; 
} 

ऊपर कोड स्वाभाविक असुरक्षित है, भले ही अस्थिर अर्थ यह है कि रीड और राईट मुख्य स्मृति में प्लावित कर रहे हैं होने के रूप में चर की घोषणा - एक ऐसी की केवल सुरक्षित कार्यान्वयन विधि कुछ ऐसा होगा:

int i = 0; 

public synchronized void foo() { 
    if (i == 0) i = i + 1; 
} 

तो आपको कौन सा पसंद करना चाहिए? खैर, यदि आपके पास उस फ़ील्ड के मान (यानी तुलना-सेट) पर निर्भर फ़ील्ड को संशोधित करने वाले एकाधिक थ्रेड हैं, तो synchronized एकमात्र सुरक्षित समाधान है।

यह भी कहने लायक है: synchronized का प्रदर्शन ओवरहेड कोई समस्या नहीं है (मामलों की भारी बहुमत में)। सिंक्रनाइज़ेशन-प्रदर्शन समस्याएं आमतौर पर अनावश्यक कोड बाधाओं, डेडलॉक्स या आजीविका के कारण होती हैं और यदि आवश्यक हो तो उन्हें कम किया जा सकता है। किसी भी शुद्ध घड़ी-चक्र भूमि के ऊपर अन्य बातों के आप आवेदन करता है द्वारा dwarfed किया जाएगा: फ़ाइल आईओ, डेटाबेस प्रश्नों, दूरस्थ बनाने आदि

+3

अस्थिरता केवल 'i ++' के लिए सुरक्षित नहीं है यदि 'i'' double' या 'long '। – abyx

+0

हां, लेकिन मुझे ऐसे मामलों में कौन सा पसंद करना चाहिए। – DKSRathore

+0

मेरा बिंदु तुलना-और सेट के बारे में था; 'अगर (i == 0) i ++' सुरक्षित नहीं है, भले ही मैं 'int' –

2

KDSRathore, आप कुछ स्पष्ट ताले उपयोग कर सकते हैं, या (कुछ डमी वस्तु वस्तु = नई वस्तु बनाने), जिस पर आप उस डबल

+1

प्राइमेटिव्स के लिए मौजूदा परमाणु रैपर का उपयोग करने की अपेक्षा अधिक अनुशंसा की जाती है। – abyx

+0

कहां कहता है कि मौजूदा परमाणु रैपर को समर्पित लॉक के लिए प्राथमिकता दी जाती है? एक समर्पित लॉक बेहतर हो सकता है क्योंकि लॉक का दायरा सीमित है। –

3

अस्थिर निश्चित रूप से जाने का तरीका है यदि आप केवल एक असाइनमेंट कर रहे हैं। मुझे यकीन है कि आप जानते हैं, लेकिन चूंकि इसे लाया गया था: यदि आप अधिक जटिल संचालन करना चाहते हैं (उदाहरण के लिए मूल्य बढ़ाएं) तो आपको सिंक्रनाइज़ करना होगा। i ++ किसी भी प्रकार के चर के लिए कभी भी थ्रेड सुरक्षित नहीं है। आपको सिंक करना होगा। i ++ और जैसा कि वास्तव में 1 से अधिक ऑपरेशन है।

नहीं

: यह व्यक्त की गई थी आप AtomicDouble इस्तेमाल कर सकते हैं, लेकिन वर्तमान में java.util.concurrent.atomic

में कोई AtomicDouble आप एक्स पर एक बहु संचालन कर रहे हैं, कि एक नया मान स्थापित की आवश्यकता है है कि वहाँ अंत में, यह थ्रेड सुरक्षित तरीके से ऐसा करना संभव है कि बिना किसी लॉकिंग के, और तुलना और सेट का उपयोग करके इसे थ्रेड सुरक्षित रखें। उदाहरण:

AtomicLong x = new AtomicLong(SomeValue); 
public void doStuff() { 
    double oldX; 
    double newX; 
    do { 
    oldX = x.get(); 
    newX = calculateNewX(oldX); 
    } while (!x.compareAndSet 
     (Double.doubleToLongBits(oldX), Double.doubleToLongBits(newX))); 

यह काम करता है क्योंकि तुलना करें औरसेट देखेंगे कि पिछली बार जब आप इसे पढ़ते हैं तो x का मान बदल गया है या नहीं। यदि एक्स बदल गया है तो आपको फिर से गणना करने के लिए मजबूर होना पड़ता है और इसे फिर से सेट करने का प्रयास करें।

आप इन डबल टोलोंग बिट्स रूपांतरणों के बजाय अपने स्वयं के परमाणु डबल को लागू कर सकते हैं। AtomicFieldUpdater पर एक नज़र डालें।

+0

अच्छा जवाब के लिए धन्यवाद। हाँ मैंने देखा कि कोई परमाणु डबल नहीं है और इसलिए मैं एक डमी ऑब्जेक्ट लॉक करने और अपना डबल असाइनमेंट करने के साथ समाप्त हुआ। आपके अनुसार अस्थिर ठीक है। लेकिन क्या यह डबल के मामले में सच है? – DKSRathore

+1

वैसे तथ्य यह है कि परमाणु लांग अपने मूल्य को अस्थिर के रूप में परिभाषित करता है और AtomicLong.set की परिभाषा केवल "मूल्य = नया वैल्यू" है, मैं इसे अच्छे सबूत के रूप में लेता हूं कि 64 बिट अस्थिर चर के पास जावा 1.6 के रूप में परमाणु असाइनमेंट हैं। –

+0

असामान्य उद्देश्य के साथ यह एक अच्छी तरह से लिखित उदाहरण है: यह तब तक स्पिन करता है जब तक कि यह अंततः 'x' मान को ओवरराइट करने में सक्षम न हो। अधिक विशिष्ट गणना एक अद्यतन मूल्य की गणना करने के लिए, इसे स्टोर करने का प्रयास करें, और विफलता पर, छोड़ने के लिए, यह मानते हुए कि कुछ अन्य धागे वहां पहुंचे और पहले स्थिति को उन्नत किया। आपके उदाहरण में अनुबंध यह है कि प्रत्येक प्रतिस्पर्धी धागा एक बार मूल्य को आगे बढ़ाएगा, विवाद के मुकाबले जो कुछ भी करता है वह कर रहा है। – seh

0

the oracle documentation के अनुसार, आप डबल वस्तु का उल्लेख करने के अस्थिर उपयोग कर सकते हैं:

volatile Double x = y; 

"करने के लिए लिखता है और संदर्भ की पढ़ता हमेशा परमाणु, चाहे वे के रूप में 32-बिट कार्यान्वित कर रहे हैं की परवाह किए बिना या 64 बिट मान। "

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

  • कोई संबंधित समस्या नहीं^_^