थ्रेड सेफ्टी
थ्रेड सेफ्टी कंप्यूटर प्रोग्रामिंग सिद्धांत है जो मल्टी-थ्रेडेड कोड पर लागू होता है। थ्रेड-सेफ्टी कोड केवल साझा डेटा संरचनाओं में चालाकी करता है जो यह सुनिश्चित करता है कि सभी थ्रेड ठीक से व्यवहार करें और बिना किसी अनपेक्षित इंटरैक्शन के अपने डिज़ाइन विनिर्देशों को पूरा करें। थ्रेड-सुरक्षित डेटा संरचनाएँ बनाने के लिए विभिन्न कार्यनीतियाँ हैं।[1][2]
प्रोग्राम एक साझा पता स्थान में एक साथ कई थ्रेड्स में कोड निष्पादित कर सकता है, जहां उन थ्रेड्स में से प्रत्येक के पास हर दूसरे थ्रेड के लगभग सभी मेमोरी तक पहुंच होती है। थ्रेड सेफ्टी गुण है जो नियंत्रण के वास्तविक प्रवाह और कार्यक्रम के पाठ के बीच समकालीन के माध्यम से कुछ पत्राचार को पुन: स्थापित करके कोड को बहुप्रचारित वातावरण में चलाने की अनुमति देती है।
थ्रेड सेफ्टी के स्तर
सॉफ्टवेयर पुस्तकालय कुछ थ्रेड-सेफ्टी गारंटी प्रदान कर सकती है। उदाहरण के लिए, समवर्ती पठन को थ्रेड-सुरक्षित होने की गारंटी दी जा सकती है, लेकिन समवर्ती लेखन नहीं हो सकता है। ऐसी पुस्तकालय का उपयोग करने वाला कोई प्रोग्राम थ्रेड-सुरक्षित है या नहीं, यह इस बात पर निर्भर करता है कि क्या वह पुस्तकालय का उपयोग उन गारंटियों के अनुरूप तरीके से करता है।
अलग-अलग विक्रेता थ्रेड-सेफ्टी के लिए थोड़ी अलग शब्दावली का उपयोग करते हैं [3][4][5][6]
- थ्रेड सुरक्षित: जब एक साथ कई थ्रेड्स द्वारा एक्सेस किए जाने पर निष्पादन को दौड़ की स्थिति से मुक्त होने की गारंटी दी जाती है।
- सशर्त रूप से सुरक्षित: विभिन्न थ्रेड्स एक साथ विभिन्न वस्तुओं तक पहुंच सकते हैं, और साझा किए गए डेटा तक पहुंच दौड़ की स्थिति से सुरक्षित है।
- नॉट थ्रेड्स सेफ: डेटा संरचनाएं को विभिन्न थ्रेड्स द्वारा एक साथ एक्सेस नहीं किया जाना चाहिए।
थ्रेड सेफ्टी गारंटी में सामान्यतः गतिरोध के विभिन्न रूपों के जोखिम को रोकने या सीमित करने के लिए डिज़ाइन चरण शामिल होते हैं, साथ ही समवर्ती प्रदर्शन को अधिकतम करने के लिए अनुकूलन भी शामिल होते हैं। हालांकि, डेडलॉक-मुक्त गारंटी हमेशा नहीं दी जा सकती है, क्योंकि डेडलॉक कॉलबैक और पुस्तकालय से स्वतंत्र वास्तु परत के उल्लंघन के कारण हो सकते हैं।
कार्यान्वयन दृष्टिकोण
नीचे हम थ्रेड-सेफ्टी प्राप्त करने के लिए दौड़ की स्थिति से बचने के लिए दृष्टिकोणों के दो वर्गों पर चर्चा करते हैं।
दृष्टिकोणों की पहली श्रेणी साझा स्थिति से बचने पर केंद्रित है और इसमें शामिल हैं
- पुन:-प्रवेश
- इस तरह से कोड लिखना कि इसे आंशिक रूप से थ्रेड द्वारा निष्पादित किया जा सकता है, उसी थ्रेड द्वारा निष्पादित किया जा सकता है, या एक साथ दूसरे थ्रेड द्वारा निष्पादित किया जा सकता है और फिर भी मूल निष्पादन को सही ढंग से पूरा कर सकता है। इसके लिए स्थिर या वैश्विक चर या अन्य गैर-स्थानीय राज्य के बजाय प्रत्येक निष्पादन के लिए स्थानीय चर में राज्य की जानकारी की बचत की आवश्यकता होती है। सभी गैर-स्थानीय राज्यों को परमाणु संचालन के माध्यम से एक्सेस किया जाना चाहिए और डेटा-संरचना भी पुनः प्रवेशी होनी चाहिए।
- थ्रेड-लोकल स्टोरेज
- परिवर्तनशील को स्थानीयकृत किया जाता है ताकि प्रत्येक थ्रेड की अपनी निजी प्रति हो। ये चर अपने मूल्यों को सबरूटीन और अन्य कोड सीमाओं में बनाए रखते हैं और थ्रेड-सुरक्षित होते हैं क्योंकि वे प्रत्येक थ्रेड के लिए स्थानीय होते हैं, भले ही उन्हें एक्सेस करने वाले कोड को एक साथ दूसरे थ्रेड द्वारा निष्पादित किया जा सकता है।
- अपरिवर्तनीय वस्तुएं
- निर्माण के बाद किसी वस्तु की स्थिति को नहीं बदला जा सकता है। इसका अर्थ यह है कि केवल पढ़ने के लिए डेटा साझा किया जाता है और अंतर्निहित थ्रेड सेफ्टी प्राप्त की जाती है। म्यूटेबल (गैर-स्थिरांक) संचालन तब इस तरह से कार्यान्वित किया जा सकता है कि वे मौजूदा वस्तुओं को संशोधित करने के बजाय नई वस्तुएं बनाते हैं। यह दृष्टिकोण कार्यात्मक प्रोग्रामिंग की विशेषता है और इसका उपयोग जावा, सी# और पायथन में स्ट्रिंग कार्यान्वयन द्वारा भी किया जाता है। (अपरिवर्तनीय वस्तु देखें।)
दूसरी श्रेणी के दृष्टिकोण तुल्यकालन से संबंधित हैं, और उन स्थितियों में उपयोग किए जाते हैं जहां साझा स्थिति से बचा नहीं जा सकता है
- पारस्परिक बहिष्कार
- साझा किए गए डेटा तक पहुंच तंत्र का उपयोग करके क्रमबद्ध किया जाता है जो यह सुनिश्चित करता है कि किसी भी समय साझा किए गए डेटा को केवल एक थ्रेड पढ़ता या लिखता है। पारस्परिक बहिष्करण को शामिल करने पर अच्छी तरह से विचार करने की आवश्यकता है, क्योंकि अनुचित उपयोग से गतिरोध, लाइवलॉक्स और संसाधन भुखमरी जैसे दुष्प्रभाव हो सकते हैं।
- परमाणु संचालन
- साझा किए गए डेटा को परमाणु संचालन का उपयोग करके प्रवेश किया जाता है जिसे अन्य थ्रेड्स द्वारा बाधित नहीं किया जा सकता है। इसके लिए सामान्यतः विशेष मशीन भाषा निर्देशों का उपयोग करने की आवश्यकता होती है, जो क्रम पुस्तकालय में उपलब्ध हो सकते हैं। चूंकि ऑपरेशन परमाणु हैं, साझा डेटा हमेशा वैध स्थिति में रहता है, इससे कोई फर्क नहीं पड़ता कि अन्य धागे इसे कैसे प्रवेश करते हैं। परमाणु संचालन कई थ्रेड लॉकिंग तंत्रों का आधार बनता है, और पारस्परिक बहिष्करण आदिम को लागू करने के लिए उपयोग किया जाता है।
उदाहरण
जावा कोड के निम्नलिखित भाग में, जावा कीवर्ड समकालिक विधि को थ्रेड-सुरक्षित बनाती है
class Counter {
private int i = 0;
public synchronized void inc() {
i++;
}
}
C प्रोग्रामिंग लैंग्वेज में, प्रत्येक थ्रेड का अपना स्टैक होता है। तथापि, एक स्थिर चर को स्टैक पर नहीं रखा जाता है, सभी थ्रेड्स इसके लिए एक साथ पहुंच साझा करते हैं। यदि एक ही फ़ंक्शन को चलाने के दौरान एकाधिक धागे अधिव्यापन होते हैं, तो यह संभव है कि एक स्थिर चर को एक थ्रेड द्वारा बदला जा सकता है जबकि दूसरा इसे जांचने के बीच में है। यह कठिन-से-निदान तर्क त्रुटि, जो अधिकांश समय संकलित और ठीक से चल सकती है, दौड़ की स्थिति सॉफ़्टवेयर कहा जाता है। इससे बचने का एक सामान्य तरीका यह है कि अन्य साझा चर को "लॉक" या "म्यूटेक्स" (पारस्परिक बहिष्करण से) के रूप में उपयोग करना है।
सी कोड के निम्नलिखित भाग में, फ़ंक्शन थ्रेड-सुरक्षित है, लेकिन पुनर्वित्तक नहीं है
# include <pthread.h>
int increment_counter ()
{
static int counter = 0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// only allow one thread to increment at a time
pthread_mutex_lock(&mutex);
++counter;
// store value before any other threads increment it further
int result = counter;
pthread_mutex_unlock(&mutex);
return result;
}
ऊपरोक्त में, increment_counter
को बिना किसी समस्या के विभिन्न थ्रेड्स द्वारा कॉल किया जा सकता है क्योंकि म्यूटेक्स का उपयोग साझा counter
चर के सभी एक्सेस को सिंक्रोनाइज़ करने के लिए किया जाता है। लेकिन अगर फ़ंक्शन का उपयोग रीएन्ट्रेंट इंटरप्ट हैंडलर में किया जाता है और म्यूटेक्स लॉक होने पर दूसरा इंटरप्ट उत्पन्न होता है, तो दूसरा रूटीन हमेशा के लिए लटका रहेगा। चूंकि इंटरप्ट सर्विसिंग अन्य इंटरप्ट्स को निष्क्रिय कर सकती है, इसलिए पूरा सिस्टम प्रभावित हो सकता है।
सी ++ 11 में लॉक-फ्री रैखिकता का उपयोग करके एक ही फ़ंक्शन को थ्रेड-सुरक्षित और पुनर्वित्तक दोनों के रूप में कार्यान्वित किया जा सकता है
# include <atomic>
int increment_counter ()
{
static std::atomic<int> counter(0);
// increment is guaranteed to be done atomically
int result = ++counter;
return result;
}
यह भी देखें
संदर्भ
- ↑ Kerrisk, Michael (2010). लिनक्स प्रोग्रामिंग इंटरफ़ेस. No Starch Press. p. 655.
- ↑ "मल्टीथ्रेडेड प्रोग्रामिंग गाइड". Oracle Corporation. November 2010.
A procedure is thread safe when the procedure is logically correct when executed simultaneously by several threads.
- ↑ "Reentrancy and Thread-Safety | Qt 5.6". Qt Project. Retrieved 2016-04-20.
- ↑ "ip::tcp – 1.51.0". Boost.org. Retrieved 2013-10-16.
- ↑ "एपीआई थ्रेड सुरक्षा वर्गीकरण". Publib.boulder.ibm.com. 1998-06-09. Retrieved 2013-10-16.[dead link]
- ↑ "MT Interface Safety Levels – Multithreaded Programming Guide". Docs.oracle.com. 2010-11-01. Retrieved 2013-10-16.
बाहरी संबंध
- Java Q&A Experts (20 April 1999). "Thread-safe design (4/20/99)". JavaWorld.com. Retrieved 2012-01-22.
- TutorialsDesk (30 Sep 2014). "Synchronization and Thread Safety Tutorial with Examples in Java". TutorialsDesk.com. Retrieved 2012-01-22.
- Venners, Bill (1 August 1998). "Design for thread safety". JavaWorld.com. Retrieved 2012-01-22.
- Suess, Michael (15 October 2006). "A Short Guide to Mastering Thread-Safety". Thinking Parallel. Retrieved 2012-01-22.