2011-03-03 16 views
15

त्वरित सवाल है, उम्मीद है कि ...अजगर सशर्त "के साथ" लॉक डिजाइन

मैं कुछ साझा बयान

def someMethod(self, hasLock = False): 
    with self.my_lock: 
     self.somethingElse(hasLock=True) 


def somethingElse(self, hasLock = False): 
    #I want this to be conditional... 
    with self.my_lock: 
      print 'i hate hello worlds" 

यही मतलब के साथ का उपयोग कर ताला लगा करने के लिए कोशिश कर रहा हूँ? मैं मूल रूप से केवल आईएफ के साथ करना चाहता हूं * मेरे पास पहले से ही लॉक नहीं है ..

इसे पूरा करने में सक्षम होने के शीर्ष पर, क्या यह एक खराब डिज़ाइन है? क्या मुझे सिर्फ खुद को प्राप्त/रिलीज़ करना चाहिए?

यह उन मस्तिष्क गोज़ प्रश्नों में से एक की तरह लगता है ..

+1

इसमें कुछ कोड गंध है। – zzzzBov

+0

अब और नहीं, मैं RLock – Nix

उत्तर

30

बस threading.RLock का उपयोग करें जो पुन: प्रवेशकर्ता है जिसका अर्थ है कि इसे एक ही थ्रेड द्वारा कई बार अधिग्रहित किया जा सकता है।

http://docs.python.org/library/threading.html#rlock-objects

स्पष्टता के लिए, RLock, with बयान में प्रयोग किया जाता है सिर्फ अपने नमूना कोड में की तरह:

lock = threading.RLock() 

def func1(): 
    with lock: 
     func2() 

def func2(): 
    with lock: # this does not block even though the lock is acquired already 
     print 'hello world' 

जहां तक ​​या नहीं, यह बुरा डिजाइन है, हम आवश्यकता होगी अधिक संदर्भ क्यों दोनों कार्यों को ताला हासिल करने की आवश्यकता है? func2func1 के अलावा कुछ और कहलाता है?

+1

बयान के साथ उपयोग करने की क्षमता बॉयलर प्लेट कोड के बहुत से को समाप्त करती है ... – Nix

+0

कभी नहीं, यह पूरी तरह से काम करता है। धन्यवाद। – Nix

+1

@Nix "इस मॉड्यूल द्वारा प्रदान की गई सभी ऑब्जेक्ट्स जो() और रिलीज() विधियों को प्राप्त करने के लिए संदर्भ प्रबंधक के रूप में उपयोग किए जा सकते हैं।" –

0

बयान के साथ का उपयोग करते हुए सिर्फ acquire() और release() कार्यों से बेहतर है। इस तरह, यदि कोई त्रुटि उत्पन्न होती है, तो ताले जारी किए जाएंगे।

+0

का उपयोग करने जा रहा हूं क्या आप सशर्त रूप से कर सकते हैं? – Nix

+0

आप सशर्त बयान नहीं कर सकते हैं, लेकिन कुछ ऑब्जेक्ट्स कथन के माध्यम से असाइनमेंट का समर्थन करते हैं। उदाहरण के लिए 'ओपन ("x.txt") के साथ f: print f.read() ' –

0

लॉकिंग लागू करने का एक शानदार तरीका है, क्योंकि लॉकिंग एक संपूर्ण संसाधन अधिग्रहण पैटर्न है। हालांकि, आपका वर्तमान उदाहरण काम नहीं करेगा, आपको कुछ के भीतर कथन के आस-पास एक कथन की आवश्यकता होगी()।

def somethingElse(self, hasLock = False): 
    #I want this to be conditional... 
    with hasLock or self.my_lock: 
      print 'i hate hello worlds' 

दुर्भाग्य से यह काफी आसान नहीं है क्योंकि एक बूलियन एक with बयान से एक वैध वापसी नहीं है:

4

अजगर orshort circuiting ताकि आप ताला सशर्त बना सकते हैं। बूलियन True मान को लपेटने के लिए आपको __enter__ और __exit__ के साथ कक्षा बनाने की आवश्यकता होगी।

यहां एक संभावित कार्यान्वयन है जिसका मैंने परीक्षण नहीं किया है।

from contextlib import contextmanager 

@contextmanager 
def withTrue(): 
    yield True 

def withbool(condition): 
    if condition: 
     return withTrue() 
    return False 

def somethingElse(self, hasLock = False): 
    with withbool(hasLock) or self.my_lock(): 
      print 'i hate hello worlds' 

यह कुछ आसान के लिए बॉयलरप्लेट है, इसलिए आरएलॉक समाधान विजेता की तरह दिखता है। हालांकि यह समाधान एक अलग संदर्भ में उपयोगी हो सकता है।

+0

यह [contextmanager] का उपयोग करने का एक अच्छा समय होगा (http://docs.python.org/library/contextlib.html#contextlib.contextmanager)। –

+1

मुझे लगता है कि यह काम करेगा, लेकिन RLock मुझे बॉक्स से बाहर की ज़रूरत है। धन्यवाद। – Nix

+0

@jleedev, धन्यवाद, मैं contextmanager के बारे में भूल गया। दुर्भाग्य से मुझे नहीं लगता कि यह इस संदर्भ में काम करेगा क्योंकि आप केवल सही मूल्य को लपेटना चाहते हैं, झूठी नहीं। –

1

नहीं क्यों:

def someMethod(self): 
    with self.my_lock: 
     self.somethingNoLock() 

def somethingElse(self): 
    with self.my_lock: 
     self.somethingNoLock() 

def somethingNoLock(self): 
    print 'i hate hello worlds" 

ध्यान दें कि जब someMethod और somethingElse मेरी समाधान में समान हैं, सामान्य रूप में वे अलग होगा। आप somethingNoLock के आस-पास एक और रैपर डाल सकते हैं ताकि लॉक अधिग्रहण और रिलीज कई बार दोहराया न जाए।

यह बहुत आसान और सीधा है। सिर्फ इसलिए कि पुन: प्रवेश लॉक हथौड़ा उपलब्ध है, मैं इसका उपयोग करने की अनुशंसा नहीं करता हूं जब इसे और अधिक सरल, कम नाजुक तरीका है।

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

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