2012-02-15 15 views
11

मैं एक फाइल सिस्टम पदानुक्रम के आधार पर लॉक करने में सक्षम होना चाहता हूं।जावा में पदानुक्रमित म्यूटेक्स ताले

थ्रेड 1: उदाहरण के लिए:

lock("/"); 
doStuff(); 
unlock(); 

थ्रेड 2:

lock("/sub/foo"); 
doStuff(); 
unlock(); 

थ्रेड 3:

lock("/sub/bar"); 
doStuff(); 
unlock(); 

थ्रेड 1 पहले तो ताला प्राप्त कर लेता है, तो सूत्र 2 और 3 होगा थ्रेड 1 अनलॉक होने तक अवरुद्ध रहें। हालांकि, अगर थ्रेड 2 पहले लॉक प्राप्त करता है, तो थ्रेड 3 थ्रेड 2 के साथ एक ही समय में निष्पादित करने में सक्षम होना चाहिए। सामान्य नियम यह है कि यदि मूल निर्देशिका पर लॉक है, तो थ्रेड को ब्लॉक करना होगा।

क्या जावा में कुछ भी अंतर्निहित है जो इसे हल करने में मदद कर सकता है? मैं प्रति निर्देशिका लॉक को संग्रहित करना चाहता हूं क्योंकि सैकड़ों हजार निर्देशिकाएं होंगी। जब भी आप उस पेड़ आप जड़ से नीचे जाना में कुछ भी ताला और लक्ष्य के अलावा सब कुछ पर एक रीड-लॉक प्राप्त करने के लिए की जरूरत है

-/
- sub 
    - foo 
    - bar 

:

+0

+1 गंभीरता से दिलचस्प प्रश्न के लिए। निर्देशिका संरचना पहले से निर्दिष्ट है, या "फाइलें" विज्ञापन-निर्माण कर सकते हैं? इसके अलावा, प्राथमिकता प्रणाली क्या है यदि एक धागा रूट निर्देशिका प्राप्त करना चाहता है जबकि कई अन्य धागे सभी व्यक्तिगत फाइलें प्राप्त करने का प्रयास करते हैं?क्या धागा जड़ चाहता है सिर्फ भूखा है, या क्या आपके पास कुछ प्रकार की गारंटी है जो आपको दिमाग में है? – templatetypedef

+0

मुझे लगता है कि अगर थ्रेड 2 लॉक प्राप्त करता है, तो थ्रेड 1 ब्लॉक करना चाहिए, है ना? – Irfy

+0

इसके पीछे प्रेरणा का हिस्सा फ़ाइल सिस्टम को संशोधित करना है, इसलिए पथ लगातार बदल रहे होंगे। मुझे यकीन नहीं है कि थ्रेड भुखमरी को कैसे संभाला जाए ... ऐसा कुछ है जिसे मैंने वास्तव में नहीं माना है। मुझे लगता है कि एक पठन/लिखने की ताला तंत्र इसे हल करने के करीब हो सकती है और भूखे धागे को संभालने में सक्षम नहीं हो सकती है। –

उत्तर

7

मैं इस तरह एक पेड़ में निर्देशिका पथ की दुकान करता हूँ खुद नोड। लक्ष्य नोड एक लेखन ताला मिलता है।

यह योजना आपको पेड़ के प्रासंगिक हिस्सों की डेडलॉक-स्वतंत्रता और स्थिरता की गारंटी देती है।

मुझे सैकड़ों हजारों ताले स्टोर करने में कोई विशेष समस्या नहीं दिखाई दे रही है। यह शायद प्रति लॉक 100 बाइट रैम बर्बाद करने जा रहा है। लेकिन यह वास्तुकला को सरल बनाता है। क्या आप वास्तव में एक समस्या है तो क्या आप मापते हैं?

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

+1

कूल दृष्टिकोण। मुझे लगता है कि काम कर सकता है। अगर मुझे प्रति निर्देशिका लॉक स्टोर करना है, तो हो सकता है। यदि संभव हो तो मैं इसे टालने की कोशिश कर रहा था। –

+0

इस प्रकार डेटाबेस लॉकिंग करते हैं। वे जड़ से बी-पेड़ पथ को पत्ते के पृष्ठों तक बंद कर देते हैं। – usr

+0

यह अच्छा लग रहा है। मैं सर्वश्रेष्ठ प्रदर्शन के लिए 'java.util.ConcurrentHashMap' के साथ जाऊंगा और मैं इसे' 'के रूप में मैप कर दूंगा। मैं विशिष्टता की गारंटी के लिए 'फ़ाइल फ़ाइल = नई फ़ाइल (स्ट्रिंगपाथ) .getCanonicalFile() 'का भी उपयोग करता हूं। लॉजिक लॉक सृजन और पढ़ने और लिखने के लिए अलग लॉकिंग के बाद तर्क को स्पष्ट रूप से स्पष्ट किया जाना चाहिए। – Irfy

0

एक और अधिक प्रदर्शन समाधान हो सकता है, लेकिन यहां मैं कैसे शुरू करूंगा।

मैं lock(path) और unlock(path) विधि के साथ एक साझा TreeAccess ऑब्जेक्ट बनाउंगा। इस विधि को एक सिंक्रनाइज़ ब्लॉक डालना होगा जो पथ उपलब्ध होने तक लूप होगा। प्रत्येक पुनरावृत्ति पर, यदि उपलब्ध नहीं है, तो यह जांच करेगा कि पथ उपलब्ध है या नहीं, और यदि नहीं, wait() कुछ अन्य थ्रेड notifyAll() पर कॉल करता है। यदि पथ उपलब्ध है, तो यह आगे बढ़ेगा, और जब पूरा हो जाए, तो अनलॉक() विधि को कॉल करें जो notifyAll() होगा।

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

public void lock(String path) { 
    synchronized (lock) { 
     while (!available(path)) { 
      lock.wait(); 
     } 
     lockedPaths.add(path); 
    } 
} 

public void unlock(String path) { 
    synchronized (lock) { 
     lockedPaths.remove(path); 
     lock.notifAll(); 
    } 
} 

private boolean available(String path) { 
    for (String lockedPath : lockedPaths) { 
     if (isParentOrEqual(lockedPath, path) { // this method is left as an exercise 
      return false; 
     } 
    } 
    return true; 
} 
संबंधित मुद्दे