वोलेटाइल (कंप्यूटर प्रोग्रामिंग)

कंप्यूटर प्रोग्रामिंग में वोलेटाइल का अर्थ कोड के अनियंत्रित होने व समय के साथ उनके मूल्य के परिवर्तित होने की संभावना है। वोलेटाइल का कार्य कॉलिंग परिपाटियों के भीतर निहितार्थ है और यह चरों को कैसे संग्रहण, अभिगम और और कैच किया जाय इस पर भी प्रभाव डालता है।

C ( प्रोग्रामिंग भाषा ), C++, C# और Java (जावा) प्रोग्रामिंग भाषा में वोलेटाइल संकेतशब्द (कंप्यूटर प्रोग्रामिंग) इंगित करता है कि वैल्यू (कंप्यूटर विज्ञान) भिन्न-भिन्न एक्सेस के मध्य परिवर्तित हो सकती है भले ही यह संशोधित प्रतीत न हो। यह संकेतशब्द अनुकूलन संकलक को बाद के रीड्स या राइट्स को इसके अनुकूल होने से रोकता है और इस प्रकार अशुद्ध रूप से पुराने मान का पुन: उपयोग करता है या राइट्स को छोड़ देता है। वोलेटाइल मान मुख्य रूप से हार्डवेयर एक्सेस (मेमोरी-मैप्ड I/O) में उत्पन्न होते हैं जहां मेमोरी से पढ़ने या लिखने का उपयोग परिधीय उपकरणों (संगणक के साथ जुड़े उपकरण) के साथ संवाद करने के लिए किया जाता है और जहां थ्रेड (कंप्यूटिंग) में अलग थ्रेड ने मान को संशोधित किया हो।

सामान्य संकेत शब्द होने के उपरांत का व्यवहार प्रोग्रामिंग भाषाओं के मध्य महत्वपूर्ण रूप से भिन्न है और त्रुटिपूर्ण समझा जाता है। C और C ++ में यह एक प्रकार का टाइप क्वालीफायर है जैसे  और डेटा एक प्रकार की संपत्ति है। इसके अतिरिक्त C और C ++ में यह अधिकांश थ्रेडिंग परिदृश्यों में काम नहीं करता है और इसका उपयोग निराशाजनक होता है। Java और C # में यह चर (कंप्यूटर विज्ञान) की संपत्ति है और इंगित करता है कि वस्तु (कंप्यूटर विज्ञान) जिसके लिए चर बाध्य है उत्परिवर्तित हो सकता है तथा विशेष रूप से थ्रेडिंग के लिए अभीष्ट है। D (प्रोग्रामिंग भाषा) प्रोग्रामिंग भाषा में थ्रेडिंग उपयोग के लिए एक अलग संकेतशब्द   होता है परन्तु कोई भी   संकेतशब्द उपलब्ध नहीं है।

C और C ++ में
C और C ++ में  संकेतशब्द का निम्नलिखित उद्देश्य था
 * मेमोरी-मैप्ड I/O उपकरणों तक पहुंच की अनुमति देना।
 * और  के मध्य चरों के उपयोग की अनुमति देना।
 * सिग्नल हैंडलर में चरों के उपयोग की अनुमति देना।

जबकि C और C ++ दोनों के द्वारा अभिप्रेत C मानक यह व्यक्त करने में विफल रहते हैं कि  सिमेंटिक्स लवल्यू को संदर्भित करता है, संदर्भित वस्तु को नहीं। संबंधित दोष रिपोर्ट DR 476 (C11 तक) अभी भी C17 (C मानक संशोधन) के साथ समीक्षाधीन है।

चरों पर संचालन परमाणु संचालन नहीं होता हैं और न ही वे थ्रेडिंग के लिए उचित होते है जोकि पहले संबंध स्थापित करते हैं। यह प्रासंगिक मानकों (C, C++, POSIX, WIN32) में निर्दिष्ट है और वोलेटाइल चर उपलब्ध कार्यान्वयन के विशाल बहुमत में थ्रेडसेफ नहीं हैं। इस प्रकार  का उपयोग पोर्टेबल सिंक्रनाइज़ेशन तंत्र के रूप में संकेतशब्द को कई C/C ++ समूहों द्वारा हतोसात्हित किया जाता है।

C में मेमोरी-मैप किए गए I/O का उदाहरण
इस उदाहरण में कोड में संग्रहीत मान   को सेट करता है तथा यह तब तक पोल (कंप्यूटर विज्ञान) आरम्भ करता है जब तक कि इसे परिवर्तित होने तक बार-बार   मूल्य नहीं मिलता:

ऑप्टिमाइज़िंग कंपाइलर इस बात का ध्यान रखता है कि कोई अन्य कोड संभवतः संग्रहीत मान  को परिवर्तित नहीं कर सकता है और मानता है कि यह   हर समय बराबर रहेगा। इसलिए कंपाइलर फ़ंक्शन बॉडी को इसके समान अनंत लूप से प्रतिस्थापित कर देता है:

जबकि  ऐसे स्थान का प्रतिनिधित्व कर सकता है जिसे किसी भी समय कंप्यूटर सिस्टम के अन्य तत्वों द्वारा परिवर्तित किया जा सकता है, जैसे कि  CPU  से जुड़े उपकरण का हार्डवेयर रजिस्टर। उपरोक्त कोड ऐसे परिवर्तन का कभी पता नहीं लगाएगा;   संकेतशब्द के बिना कंपाइलर मानता है कि वर्तमान प्रोग्राम सिस्टम का एकमात्र भाग है जो मूल्य को परिवर्तित सकता है (जो अब तक की सबसे सामान्य स्थिति है)।

ऊपर के रूप में कोड को अनुकूलित करने से संकलक को रोकने के लिए  संकेतशब्द प्रयोग किया जाता है:

इस संशोधन के साथ लूप की स्थिति को अनुकूलित नहीं किया जाएगा और जब यह होता है तो सिस्टम परिवर्तन का पता लगाएगा।

सामान्य रूप से प्लेटफ़ॉर्म पर स्मृति बाधा संचालन उपलब्ध होते हैं (जो C++11 में उजागर होते हैं) जिन्हें वोलेटाइल के अतिरिक्त प्राथमिकता दी जानी चाहिए क्योंकि वे कंपाइलर को उन्नत अनुकूलन करने की अनुमति देते हैं और इससे भी महत्वपूर्ण बात यह है कि वे बहु-थ्रेडेड परिदृश्यों में सही व्यवहार की गारंटी देते हैं; न तो C विनिर्देश (C 11 से पहले) और न ही C ++ विनिर्देश (C ++ 11 से पहले) बहु-थ्रेडेड मेमोरी मॉडल निर्दिष्ट करता है इसलिए वोलेटाइल ओएस/कंपाइलर/सीपीयू में निश्चित रूप से व्यवहार नहीं कर सकता है।

C में अनुकूलन तुलना
निम्नलिखित C कार्यक्रम और साथ में असेंबलर भाषा अंश प्रदर्शित करते हैं कि कैसे  संकेतशब्द कंपाइलर के आउटपुट को प्रभावित करता है। इस स्थिति में संकलक GNU संकलक संग्रह था।

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

C ++ 11
C++11 ISO मानक के अनुसार वोलेटाइल संकेतशब्द मात्र हार्डवेयर एक्सेस के लिए उपयोग के लिए है; इंटर-थ्रेड संचार के लिए इसका उपयोग न करें। इंटर-थ्रेड संचार के लिए मानक पुस्तकालय  टेम्पलेट्स प्रदान करता है ।

जावा (Java) में
जावा प्रोग्रामिंग भाषा में भी  संकेतशब्द है परन्तु इसका उपयोग कुछ विभिन्न उद्देश्य के लिए किया जाता है। जब किसी क्षेत्र में लागू किया जाता है तो जावा क्वालीफायर   निम्नलिखित गारंटी प्रदान करता है: का उपयोग करते हुए लॉक (कंप्यूटर विज्ञान) से तीव्र हो सकता है परन्तु यह जावा 5 से पूर्व कुछ स्थितियों में काम नहीं करेगा। जावा 5 में वोलेटाइल स्थितियों की श्रेणी का विस्तार किया गया था; विशेष रूप से डबल-चेक लॉकिंग अब सही प्रकार से काम करती है।
 * जावा के सभी संस्करणों में सभी वोलेटाइल चरों के पढ़ने और लिखने पर एक वैश्विक क्रम है (वोलेटाइल पर यह वैश्विक क्रम बड़े तुल्यकालन क्रम पर आंशिक क्रम है (जो सभी तुल्यकालन क्रियाओं पर कुल क्रम है))। इसका तात्पर्य है कि प्रत्येक थ्रेड (कंप्यूटर विज्ञान) वोलेटाइल क्षेत्र तक पहुँचने से पहले कैच मान का उपयोग करने के स्थान पर (संभावित रूप से) जारी रखने से पहले अपने वर्तमान मूल्य को पढ़ेगा। (जबकि नियमित पढ़ने और लिखने के साथ वोलेटाइल पढ़ने और लिखने के सापेक्ष क्रम के विषय में कोई गारंटी नहीं है जिसका अर्थ है कि यह सामान्य रूप से उपयोगी थ्रेडिंग निर्माण नहीं है।)
 * जावा 5 या उसके बाद के वोलेटाइल पढ़ते है और लिखते है तथा म्यूटेक्स को प्राप्त करने और जारी करने की तरह पूर्व-संबंध स्थापित करता है।

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

केवल निम्न प्रकारों को  चिह्नित किया जा सकता है: सभी संदर्भ प्रकार, ,  ,  ,  ,  ,  ,  ,  ,  , और सभी प्रगणित प्रकार एक अंतर्निहित प्रकार के साथ  ,  ,  ,  ,  , या  । (इसमें वैल्यू स्ट्रक्चर्स के साथ ही मूल प्रकार  ,  ,   और  सम्मिलित नहीं हैं)।

संकेतशब्द का उपयोग उन क्षेत्रों का समर्थन नहीं करता है जो जो संदर्भ द्वारा पारित (कंप्यूटर प्रोग्रामिंग) किए गए हैं या स्थानीय चर पर जिनका अधिकार है; ऐसी स्थितियों में  और   उपयोग करना चाहिए।

वास्तव में ये विधियाँ सामान्यतः C # कंपाइलर, JIT कंपाइलर या स्वयं CPU द्वारा किए गए कुछ अनुकूलन को अक्षम कर देती हैं। द्वारा प्रदान की गई गारंटी  और   द्वारा प्रदान की गई गारंटी   संकेतशब्द का सुपरसेट है: आधा फेंस उत्पन्न करने के स्थान पर (अर्थात अधिग्रहण-फेंस केवल निर्देश पुनर्व्यवस्था और कैचिंग को रोकता है जो इससे पहले आता है),   और   पूर्ण फेंस उत्पन्न करते हैं जो दोनों दिशाओं में उस क्षेत्र के निर्देश पुनर्क्रमण और कैचिंग को रोकता है। ये उपाय इस प्रकार कार्य करते हैं:
 * विधि फ़ील्ड में मान को कॉल के बिंदु पर लिखे जाने के लिए बाध्य करती है। इसके अतिरिक्त किसी भी पुराने प्रोग्राम-ऑर्डर लोड और स्टोर को कॉल करने से पहले होना चाहिए और किसी भी बाद के प्रोग्राम-ऑर्डर लोड और स्टोर कॉल के बाद होने चाहिए।
 * विधि कॉल के बिंदु पर फ़ील्ड में मान को पढ़ने के लिए बाध्य करती है। इसके अतिरिक्त किसी भी पुराने प्रोग्राम-ऑर्डर लोड और स्टोर को कॉल करने से पहले  होना चाहिए और किसी भी बाद के प्रोग्राम-ऑर्डर लोड और स्टोर कॉल के बाद होने चाहिए।   और   विधियाँ कॉल करके एक पूर्ण फेंस उत्पन्न करती हैं तथा   विधि मेमोरी बैरियर का निर्माण करती है जो दोनों दिशाओं में काम करती है। ऊपर दिए गए पूर्ण फेंस का उपयोग करने के लिए प्रेरणाओं के अतिरिक्त एक संभावित समस्या   द्वारा उत्पन्न एक पूर्ण फेंस का उपयोग करके हल किया गया संकेतशब्द   इस प्रकार है: आधा फेंस की असममित प्रकृति के कारण   पढ़ने के निर्देश के पश्चात लेखन निर्देश के साथ फ़ील्ड में अभी भी संकलक द्वारा निष्पादन आदेश स्वैप किया जा सकता है क्योंकि पूर्ण फेंस सममित हैं एवं  उपयोग करते समय यह कोई समस्या नहीं है।

फोरट्रान में
फोरट्रान 2003 मानक का भाग है जबकि पहले के संस्करण ने इसे विस्तार के रूप में समर्थित किया था। सभी चर बनाना  किसी फ़ंक्शन में अलियासिंग (कंप्यूटिंग) संबंधित बग खोजने में भी उपयोगी है। वोलाटाइल की मेमोरी में सदैव "ड्रिलिंग डाउन" करने से फोरट्रान कंपाइलर द्वारा वोलाटाइल्स को पढ़ने या लिखने के क्रम को फिर से व्यवस्थित करने से रोक दिया जाता है। यह और इसके विपरीत इस थ्रेड में की गई अन्य थ्रेड क्रियाओं को यह दिखाई देता है।

वोलेटाइल का उपयोग अनुकूलन को कम करता है और रोक भी सकता है।

बाहरी संबंध

 * Ada Reference Manual C.6: Shared Variable Control
 * Linux kernel: volatile-considered-harmful