2009-12-05 8 views
8

मेरे पास दो सरणी हैं, और मुझे थ्रेड में उनके लिए पहुंच सिंक्रनाइज़ करने की आवश्यकता है। मैं उन्हें एक सिंक्रनाइज़ ब्लॉक में डाल रहा हूं। समस्या यह है कि, मैं उनमें से केवल एक को 'सिंक्रनाइज़' करने के लिए पास कर सकता हूं।जावा 1 सिंक्रनाइज़ ब्लॉक 1 से अधिक वस्तुओं के लिए?

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

धन्यवाद,

+0

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

उत्तर

20

तुम जो भी कर ऐसा नहीं करते हैं:

synchronized (array1) { 
    synchronized (array2) { 
    // do stuff 
    } 
} 

यह deadlock करने के लिए नेतृत्व की संभावना है जब तक आप बहुत सावधान कर रहे हैं। यदि आप इस दृष्टिकोण को करते हैं, तो आपको यह सुनिश्चित करना होगा कि आपके पास वस्तुओं पर एक अपरिवर्तनीय आंशिक क्रम है - Google "डाइनिंग फिलॉसॉफर्स" को नुकसान के बारे में चर्चा के लिए।

मूल रूप से आप क्या करना है एक ताला उद्देश्य यह है कि क्या आप या तो सरणी का उपयोग करना चाहते हैं का उपयोग करेगा और उसके बाद का उपयोग करें कि सभी सरणी पहुँच के लिए पैदा करते हैं। यह मोटे अनाज लेकिन सुरक्षित है। आप एक बेहतर सुक्ष्म विधि आप ReadWriteLock के रूप में जावा 5 + समवर्ती ऐसे उपयोगिताओं का उपयोग करना चाहते जरूरत है, लेकिन यह अधिक लागू करने के लिए जटिल और त्रुटि प्रवण हो जाएगा

public static class TwoArrays { 
    private int[] array1 = ... 
    private int[] array2 = ... 
    private final Object LOCK = new Object(); 

    public void doUpdate() { 
    synchronized (LOCK) { 
     ... 
    } 
    } 
} 

: आप इसे इस तरह से कर सकता है।

+1

आप 'LOCK' ऑब्जेक्ट की अतिरिक्त जटिलता के बजाय, 'doUpdate' सिंक्रनाइज़ भी कर सकते हैं। – skaffman

+3

असल में नहीं, यह सबसे अच्छा अभ्यास है कि आप अपने ताले का पर्दाफाश न करें, जो आप लॉक के रूप में उपयोग करते समय कर रहे हैं। – cletus

+0

इससे कोई प्रश्न उठता है - नेस्टेड सिंक्रनाइज़ किए गए ब्लॉक का उपयोग करके एक ही वस्तु पर एक और सिंक्रनाइज़ेशन होने पर, डेडलॉक हो सकता है। लेकिन क्या ऐसा तब होगा जब उपरोक्त कोड मौजूद है? कोई थ्रेड सरणी 2 की मॉनिटर प्राप्त नहीं कर सकता है अगर इसमें पहले से ही array1 की मॉनिटर नहीं है। और यदि इसमें array1 की मॉनिटर है, तो कोई अन्य थ्रेड सरणी 2 की मॉनीटर नहीं रख सकता है। क्या मेरे तर्क में मेरा छेद है? – Bozho

11

इस तरह जावा 5 से पहले, मैं लिखा है से ऐसे कार्य:

// pre Java 5 code: 
Object lock = new Object(); 
// ... 
synchronized(lock) { 
    // do something that requires synchronized access 
} 

लेकिन चूंकि जावा 5, मैं java.util.concurrent.locks (से कक्षाओं का उपयोग करेंगे व्यक्तिगत रूप से, मैं इस और अधिक जटिल या त्रुटि नहीं मिल रहा है -prone):

private ReadWriteLock rwl = new ReentrantReadWriteLock(); 
private Lock rLock = rwl.readLock(); 
private Lock wLock = rwl.writeLock(); 

private List<String> data = new ArrayList<String>(); 

public String getData(int index) { 
    rLock.lock(); 
    try { 
     return data.get(index); 
    } finally { 
     rLock.unlock(); 
    } 
} 

public void addData(int index, String element) { 
    wLock.lock(); 
    try { 
     data.add(index, element); 
    } finally { 
     wLock.unlock(); 
    } 
} 
:

// Java 5 Code Using Locks 
Lock lock = // ... 
lock.lock(); 
try { 
    // do something that requires synchronized access 
} 
finally { 
    lock.unlock(); 
} 

आप पढ़ने-लिखने की लॉकिंग की जरूरत है, यहाँ उदाहरण जावा 5 से पढ़ने-लिखने ताले का उपयोग कर लागू किया है

बेशक, इसे अपनी आवश्यकताओं के अनुरूप अनुकूलित करें।