2009-07-07 17 views
45

मेरे पास एक स्थिर टाइमर क्लास है जिसे किसी भी वेबपृष्ठ द्वारा कॉल किया जाएगा ताकि गणना की जा सके कि प्रत्येक पृष्ठ को कितनी देर तक बनाया जाना है।स्थिर विधियां थ्रेड सुरक्षित हैं

मेरा प्रश्न है स्टेटिक क्लास थ्रेड सुरक्षित है? मेरे उदाहरण में समवर्ती उपयोगकर्ता मेरी शुरुआत और बंद समय के साथ एक समस्या का कारण बनेंगे? उदाहरण के लिए मेरी शुरुआत को ओवरराइट करने और मूल्यों को रोकने के लिए एक अलग धागे।

public static class Timer 
{ 
    private static DateTime _startTime; 
    private static DateTime _stopTime;  

    /// <summary> 
    /// Gets the amount of time taken in milliseconds 
    /// </summary> 
    /// <returns></returns> 
    public static decimal Duration() 
    { 
     TimeSpan duration = _stopTime - _startTime; 
     return duration.Milliseconds; 
    } 

    public static void Start() 
    { 
     _startTime = DateTime.Now; 
    } 

    public static void Stop() 
    { 
     _stopTime = DateTime.Now; 
    } 
} 

क्या यह कक्षा एक गैर-स्थैतिक वर्ग होनी चाहिए?

(इस वर्ग asp.net masterpage से बुलाया जाएगा।)

+7

एमएसडीएन: "जबकि कक्षा के एक उदाहरण में कक्षा के सभी उदाहरण क्षेत्रों की एक अलग प्रति है, प्रत्येक स्थिर क्षेत्र की केवल एक प्रति है।" – colithium

उत्तर

56

स्थिर तरीके स्वाभाविक रूप से थ्रेड-सुरक्षित नहीं हैं। उदाहरण विधियों की तुलना में सीएलआर द्वारा उनका कोई अलग व्यवहार नहीं किया जाता है। अंतर यह है कि आम तौर पर उन्हें थ्रेड-सुरक्षित बनाने की कोशिश करनी चाहिए। (मैं किसी भी .NET बीसीएल स्थिर विधियों के बारे में नहीं सोच सकता जो थ्रेड-सुरक्षित नहीं हैं।) इंस्टेंस विधियां अक्सर थ्रेड-सुरक्षित नहीं होती हैं क्योंकि सामान्य पैटर्न ऑब्जेक्ट बनाने और इसे एक थ्रेड से बार-बार उपयोग करने के लिए होता है, और यदि यह को कई धागे से उपयोग किया जाना है, इसमें शामिल समन्वय में यह सुनिश्चित करना शामिल है कि ऑब्जेक्ट सुरक्षित रूप से उपयोग किया जाता है। बहुत से मामलों में ऑब्जेक्ट की तुलना में समन्वय कोड में करना अधिक उचित है। (आमतौर पर आप के संचालन को प्रभावी ढंग से परमाणु के पूरे दृश्यों बनाना चाहते - जो कुछ वस्तु के भीतर नहीं किया जा सकता।)

आपका Timer वर्ग सबसे निश्चित रूप से थ्रेड-सुरक्षित नहीं है: दो धागे आसानी से एक-दूसरे के डेटा पर stomp कर सकते हैं , और अवधि की गणना करते समय "स्टेल" डेटा का उपयोग करने से धागे को रोकने के लिए कुछ भी नहीं है।

इसके बजाय Stopwatch कक्षा का उपयोग करें - यही वह है जो इसके लिए है। माना जाता है कि यदि आप एकाधिक थ्रेड से एक उदाहरण का उपयोग करना चाहते हैं तो आपको सुरक्षा सुनिश्चित करने के लिए सामान्य कदम उठाने की आवश्यकता होगी, लेकिन आप सामान्य रूप से एक बेहतर स्थिति में होंगे। माना जाता है कि Stopwatch भी सही से बहुत दूर है - this question और अधिक जानकारी के लिए नीचे दी गई टिप्पणी देखें - लेकिन कम से कम यह किस प्रकार के लिए डिज़ाइन किया गया है। (कौन जानता है, इसे कुछ समय तय किया जा सकता है ...)

+4

स्टॉपवॉच क्लास में स्वयं की समस्याएं हैं, यदि आप इसे एकाधिक कोर या एकाधिक प्रोसेसर के साथ उपयोग कर रहे हैं। स्टॉपवॉच समय अवधि निर्धारित करने के लिए टिक गणना का उपयोग करता है और बीआईओएस में एक बग के कारण, स्टॉपवॉच एक कोर पर शुरू किया जा सकता है और दूसरे पर रुक सकता है, जहां दो कोरों पर टिक गणना सिंक से बाहर होती है। मैंने इसे Vss2Git ओपन सोर्स एप्लिकेशन में खोजा, जिसने स्टॉपवॉच का इस्तेमाल किया और कभी-कभी नकारात्मक समय अवधि देने का प्रयास किया। एफआरआर अधिक जानकारी देखें http://stackoverflow.com/a/7919483/216440 –

+1

@ सिमन ट्वेसी: हाँ, मैंने इसके बारे में पहले सुना है। उत्तर में एक लिंक संपादित करेंगे। –

4

हाँ, तुम सही हो, स्थिर सदस्यों/इस वर्ग पर accessors का कारण होगा उन्हें अलग-अलग उपयोगकर्ताओं द्वारा ओवरराइट किया जाना है।

यही कारण है कि आपके पास उदाहरण और गैर स्थैतिक सदस्य हैं।

18

आपकी टाइमर क्लास निश्चित रूप से थ्रेड-सुरक्षित नहीं है। आप एक सामान्य वर्ग बना सकते हैं और यह हर बार जब आप समय को मापने की जरूरत का दृष्टांत चाहिए:

Timer timer = new Timer(); 

timer.Start(); 
//... 
timer.Stop(); 

decimal duration = timer.Duration(); 

अभी भी बेहतर है, वहाँ है एक निर्मित .NET वर्ग कि वास्तव में करता है:

Stopwatch sw = Stopwatch.StartNew(); 

sw.Stop(); 

TimeSpan duration = sw.Elapsed; 
20

वहाँ एक अच्छी चर्चा here है जो तंत्र और अधिक कारणों पर केंद्रित है कि आपका उदाहरण थ्रेड-सुरक्षित क्यों नहीं है।

संक्षेप में, पहले, आपके स्थिर चर साझा किए जाएंगे। यदि आप उन्हें स्थानीय चर बना सकते हैं, भले ही वे स्थिर विधि के लिए स्थानीय हों, फिर भी उन्हें अपना स्वयं का ढेर फ्रेम मिल जाएगा, और इस प्रकार, थ्रेड-सुरक्षित हो। साथ ही, यदि आप अन्यथा अपने स्थिर चर (यानी ताले और/या अन्य थ्रेड-थ्रेड प्रोग्रामिंग तकनीकों को इस थ्रेड में दूसरों द्वारा उल्लिखित) की रक्षा करते हैं तो आप अपना नमूना स्थिर वर्ग थ्रेड-सुरक्षित भी बना सकते हैं।

दूसरा, क्योंकि आपका उदाहरण बाह्य परिवर्तनीय उदाहरणों में नहीं लेता है जिसे आप संशोधित करते हैं या जिनके राज्य को किसी अन्य थ्रेड द्वारा कार्य किया जा सकता है, आपका उदाहरण उस संबंध में थ्रेड-सुरक्षित भी है।

+0

उत्कृष्ट जानकारी, यह वही है जो मैं यहां खोजने के लिए आया था: यदि एक स्थिर विधि केवल स्थानीय चर का उपयोग करती है, तो क्या यह थ्रेड-सुरक्षित है? चीयर्स। –

+4

हां। लेकिन याद रखें, इसे विधि के लिए एक परिवर्तनीय स्थानीय होना चाहिए - स्थिर वर्ग चर नहीं। (मुझे लगता है कि कभी-कभी कक्षा चर को स्थानीय के रूप में जाना जाता है, लेकिन मुझे इसके बारे में गलत पता चला जा सकता है।) चूंकि आपने कहा था "केवल एक स्थानीय चर का उपयोग करता है", मैं यह भी कहता हूं कि आप पास-इन का संदर्भ निर्दिष्ट नहीं कर रहे हैं एक स्थानीय चर के लिए पैरामीटर। – Bill

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