AtomicInteger lazySet बनाम सेट


116

के lazySetऔर setतरीकों के बीच अंतर क्या है AtomicInteger? प्रलेखन ज्यादा के बारे में कहने के लिए नहीं है lazySet:

अंततः दिए गए मान पर सेट होता है।

ऐसा लगता है कि संग्रहीत मूल्य तुरंत वांछित मूल्य पर सेट नहीं किया जाएगा, बल्कि भविष्य में कुछ समय निर्धारित करने के लिए निर्धारित किया जाएगा। लेकिन, इस पद्धति का व्यावहारिक उपयोग क्या है? कोई उदाहरण?

जवाबों:


114

"JDK-6275329 से सीधे उद्धृत : परमाणु कक्षाओं में आलसी तरीके जोड़ें" :

जैसा कि संभवत: मस्तंग के लिए आखिरी थोड़ा JSR166 फॉलो-अप है, हमने एटॉमिक क्लासेस (AtomicInteger, AtomicReference, आदि) में एक "आलसीसेट" विधि जोड़ी। यह एक आला तरीका है जो कभी-कभी उपयोगी होता है जब गैर-अवरुद्ध डेटा संरचनाओं का उपयोग करके ठीक-ट्यूनिंग कोड होता है। शब्दार्थ यह है कि लिखने की गारंटी है कि किसी भी पिछले लेखन के साथ फिर से आदेश नहीं दिया जा सकता है, लेकिन बाद के संचालन (या समकक्ष, अन्य थ्रेड्स के लिए दृश्यमान नहीं हो सकता है) के साथ फिर से व्यवस्थित किया जा सकता है जब तक कि कुछ अन्य वाष्पशील लेखन या सिंक्रनाइज़ेशन क्रिया नहीं होती है)।

मुख्य उपयोग मामला गैर-अवरुद्ध डेटा संरचनाओं में नोड्स के क्षेत्रों को पूरी तरह से हटाने के लिए है, केवल लंबी अवधि के कचरा प्रतिधारण से बचने के लिए; यह तब लागू होता है जब यह हानिरहित होता है यदि अन्य थ्रेड्स थोड़ी देर के लिए गैर-शून्य मान देखते हैं, लेकिन आप यह सुनिश्चित करना चाहेंगे कि संरचनाएं अंततः GCable हैं। ऐसे मामलों में, आप अशक्त अस्थिर-लेखन की लागतों से बचकर बेहतर प्रदर्शन प्राप्त कर सकते हैं। गैर-संदर्भ-आधारित परमाणु के लिए इन पंक्तियों के साथ कुछ अन्य उपयोग के मामले भी हैं, इसलिए यह विधि सभी परमाणु वर्गों में समर्थित है।

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


14
क्या हम में से कोई इसे गूंगा कर सकता है? :(
गौरव

14
आलसी गैर-वाष्पशील संस्करण है (उदाहरण के लिए राज्य परिवर्तन की उन सभी थ्रेड्स में दृश्यमान होने की गारंटी नहीं है, Atomic*जिनमें गुंजाइश है)।
जम्हाई

63
मुझे समझ में नहीं आता है कि इसके बारे में javadoc इतना खराब क्यों है।
फेलिप

8
मुझे यकीन है कि वे अंततः इसे बदलने के लिए गोल हो जाएंगे। बूम बूम।
MMJZ

3
उन लोगों के लिए जो स्टोर / लोड बैरियर के बारे में अधिक जानना चाहते हैं और स्टोर-स्टोर बैरियर स्टोर-लोड बैरियर से सस्ता क्यों है। इसके बारे में लेख को समझना आसान है। यांत्रिक-
परिजन चेउंग

15

lazySet का उपयोग rmw इंटर थ्रेड कम्युनिकेशन के लिए किया जा सकता है, क्योंकि xchg परमाणु है, दृश्यता के लिए, जब लेखक थ्रेड प्रक्रिया एक कैश लाइन लोकेशन को संशोधित करती है, तो रीडर थ्रेड का प्रोसेसर इसे अगले रीड पर देखेगा, क्योंकि इंटेल सीपीयू का कैश कोऑरेन्स प्रोटोकॉल garantee होगा LazySet काम करता है, लेकिन कैश लाइन को अगले रीड में अपडेट किया जाएगा, फिर से, सीपीयू को पर्याप्त आधुनिक बनाना होगा।

http://sc.tamu.edu/systems/eos/nehalem.pdf नेह्म के लिए जो कि एक मल्टी-प्रोसेसर प्लेटफॉर्म है, प्रोसेसर के पास सिस्टम मेमोरी और अन्य प्रोसेसर के एक्सेस के लिए एड्रेस बस "स्नूप" (ईवॉड्र्स) की क्षमता है। उनके आंतरिक कैश के लिए। वे अपने आंतरिक कैश को सिस्टम मेमोरी और अन्य इंटरकनेक्टेड प्रोसेसर में कैश के साथ संगत रखने के लिए इस स्नूपिंग क्षमता का उपयोग करते हैं। यदि स्नूपिंग के माध्यम से एक प्रोसेसर यह पता लगाता है कि एक अन्य प्रोसेसर एक मेमोरी लोकेशन पर लिखने का इरादा रखता है जिसे उसने वर्तमान में साझा स्थिति में कैश किया है, तो स्नूपिंग प्रोसेसर उसके कैश ब्लॉक को अमान्य कर देगा जिससे वह कैश लाइन का प्रदर्शन करने के लिए अगली बार उसी मेमोरी लोकेशन को भर सके। ।

x86 cpu आर्किटेक्चर के लिए oracle हॉटस्पॉट jdk->

lazySet == unsafe.putOrderedLong == xchg rw (asm निर्देश जो नेहेम इंटेल सीपीयू पर 20 चक्रों की लागत वाली एक नरम बाधा के रूप में कार्य करता है)

x86 (x86_64) पर ऐसा अवरोध अस्थिर या एटॉमिकलॉन्ग getAndAdd की तुलना में बहुत सस्ता प्रदर्शन-वार है,

एक निर्माता, एक उपभोक्ता कतार परिदृश्य में, xchg सॉफ्ट बैरियर, निर्माता थ्रेड के लिए लेज़सेट (अनुक्रम + 1) से पहले कोड की लाइन को बाध्य कर सकता है ताकि कोई भी उपभोक्ता थ्रेड कोड हो, जो नए डेटा का उपभोग (कार्य) करेगा, उपभोक्ता थ्रेड को एटोमिकली जांचने की आवश्यकता होगी कि प्रोडयूसर सीक्वेंस को एक तुलना एसेटसेट (सीक्वेंस, सीक्वेंस + ए) का उपयोग करके बढ़ाया गया था।

मैंने हॉटस्पॉट स्रोत कोड के बाद lppSet से cpp कोड की सटीक मैपिंग का पता लगाने के लिए पता लगाया: http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/unsafe। cpp Unsafe_setOrderedLong -> SET_FIELD_VOLATILE परिभाषा -> क्रमबद्ध: release_store_fence। X86_64 के लिए, OrderAccess: release_store_fence को xchg निर्देश के उपयोग के रूप में परिभाषित किया गया है।

आप यह देख सकते हैं कि यह वास्तव में jdk7 में कैसे परिभाषित किया गया है (JDK 8 के लिए कुछ नए सामान पर काम कर रहा है): http://hg.openjdk.java.net/jdk7/jdk7/hotdot/file/4fc084dac61e/src/os_cpu/ linux_x86 / VM / orderAccess_linux_x86.inline.hpp

आप कार्रवाई में lazySet कोड की असेंबली को अलग करने के लिए भी hdis का उपयोग कर सकते हैं।

एक और संबंधित प्रश्न है: क्या हमें xchg का उपयोग करते समय mfence की आवश्यकता है


5
यह समझना मुश्किल है कि आप यहाँ क्या कर रहे हैं। क्या आप कृपया अपनी बात स्पष्ट कर सकते हैं?
पॉल बेलोरा

3
"lazySet == unsafe.putOrderedLong == xchg rw (asm निर्देश जो x86_ x86_64 पर एक नरम अवरोधक के रूप में काम करता है जो nehelem Intel cpu पर 20 चक्र खर्च करता है) (x86_64) इस तरह का अवरोध अस्थिर या एटॉमिकलॉन्ग getAndAdd की तुलना में बहुत सस्ता प्रदर्शन-वार है" -> यह मेरे सर्वश्रेष्ठ ज्ञान के लिए सही नहीं है। lazySet / putOrdered एक पते का एक MOV है, यही वजह है कि JMM रसोई की किताब इसे x86 पर एक नो-ऑप के रूप में वर्णित करती है।
निट्सन वकार्ट

11

आलसी की उत्पत्ति और उपयोगिता की व्यापक चर्चा और अंतर्निहित पुट को यहां पाया जा सकता है: http://psy-lob-saw.blogspot.co.uk/2012/12/atomiclazyset-is-perverance-win-for.html

संक्षेप में: आलसीसेट इस अर्थ में एक कमजोर अस्थिर लेखन है कि यह स्टोर-स्टोर के रूप में कार्य करता है न कि स्टोर-लोड बाड़ के रूप में। यह आलसी के लिए उबलता है जेआईटी को एक एमओवी निर्देश के लिए संकलित किया जाता है जिसे संकलक द्वारा फिर से आदेश नहीं दिया जा सकता है, फिर एक अस्थिर सेट के लिए उपयोग किए जाने वाले काफी अधिक महंगे निर्देश।

जब आप मूल्य पढ़ते हैं तो आप हमेशा एक वाष्पशील पढ़ते हैं (किसी भी मामले में परमाणु * .get () के साथ)।

lazySet एकल लेखक को एक सुसंगत वाष्पशील लेखन तंत्र प्रदान करता है, अर्थात यह एक एकल लेखक के लिए एक काउंटर को बढ़ाने के लिए lazySet का उपयोग करने के लिए पूरी तरह से वैध है, एक ही काउंटर को बढ़ाने वाले कई थ्रेड्स को CAS के साथ प्रतिस्पर्धात्मक लेखन को हल करना होगा, जो वास्तव में होता है incAndGet के लिए परमाणु * के कवर।


वास्तव में, हम क्यों यह नहीं कह सकते कि यह एक सरल है StoreStoreबाधा है, लेकिन नहीं एक StoreLoad?
यूजीन

8

से समवर्ती परमाणु पैकेज सारांश

lazySet में एक वाष्पशील चर लिखने (असाइन करने) का मेमोरी इफेक्ट होता है, सिवाय इसके कि यह बाद में (लेकिन पिछले नहीं) मेमोरी क्रियाओं के साथ रीऑर्डरिंग की अनुमति देता है जो खुद को साधारण गैर-वाष्पशील लेखन के साथ पुन: व्यवस्थित करने की बाधाओं को लागू नहीं करते हैं। अन्य उपयोग के संदर्भों में, लाजसेट लागू हो सकता है, जब कचरा संग्रह के लिए बाहर निकलना होता है, एक संदर्भ जो फिर कभी एक्सेस नहीं किया जाता है।

यदि आप आलसी के बारे में उत्सुक हैं तो आप अपने आप को अन्य स्पष्टीकरण भी देते हैं

एटॉमिक्स के एक्सेस और अपडेट के लिए मेमोरी इफेक्ट्स आमतौर पर वाष्पशील के लिए नियमों का पालन करते हैं, जैसा कि जावा ™ भाषा विनिर्देश की धारा 17.4 में कहा गया है।

एक अस्थिर चर को पढ़ने के स्मृति प्रभाव प्राप्त होते हैं।

सेट में वाष्पशील चर लिखने (असाइन करने) का मेमोरी इफेक्ट होता है।

lazySet में एक वाष्पशील चर लिखने (असाइन करने) का मेमोरी इफेक्ट होता है, सिवाय इसके कि यह बाद में (लेकिन पिछले नहीं) मेमोरी क्रियाओं के साथ रीऑर्डरिंग की अनुमति देता है जो खुद को साधारण गैर-वाष्पशील लेखन के साथ पुन: व्यवस्थित करने की बाधाओं को लागू नहीं करते हैं। अन्य उपयोग के संदर्भों में, लाजसेट लागू हो सकता है, जब कचरा संग्रह के लिए बाहर निकलना होता है, एक संदर्भ जो फिर कभी एक्सेस नहीं किया जाता है।

कमजोरकंपनीएंडसेट एटोमिकली पढ़ता है और सशर्त रूप से एक वैरिएबल लिखता है, लेकिन कोई भी ऐसा नहीं करता है-ऑर्डर से पहले।

ComparAndSet और अन्य सभी रीड-एंड-अपडेट ऑपरेशंस जैसे getAndIncrement में वाष्पशील चर को पढ़ने और लिखने दोनों का मेमोरी इफेक्ट होता है।


4

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


1
क्या आपका मतलब नहीं है compareAndSet?
डेव मोटेन

2

इसे नीचे गूंगा करने का प्रयास -

आप इसे एक अस्थिर क्षेत्र के इलाज के तरीके के रूप में सोच सकते हैं जैसे कि यह किसी विशेष स्टोर (जैसे: = null;) ऑपरेशन के लिए अस्थिर नहीं था।

यह पूरी तरह से सही नहीं है, लेकिन यह पर्याप्त होना चाहिए कि आप "ठीक है, मुझे वास्तव में परवाह नहीं है" और "हम्म, मुझे थोड़ा इसके बारे में सोचने दें"।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.