2012-06-30 35 views
12

की एक डमी वस्तु के साथ सिंक्रनाइज़ मैं निम्नलिखित कई बारबजाय इस

class Foo { 
    private Object lock = new Object(); 

    public void doSomething() { 
     synchronized(lock) { 
     ... 

की तरह कोड का सामना करना पड़ा क्या मैं क्यों एक ताला वस्तु synchronized(this) लिखने की बजाय बनाया जाता है में दिलचस्पी रखता हूँ? क्या यह लॉक साझा करने में सक्षम है? मुझे बेहद याद है कि यह एक अनुकूलन है। क्या यह सच है? साथ ही, क्या, कुछ संदर्भ में, लॉक को final के रूप में घोषित करने का अर्थ है?

+0

इस प्रश्न का उत्तर यहां दिया गया है: http://stackoverflow.com/a/3369303/1343161 – Keppil

उत्तर

23
  1. this पर सिंक्रनाइज़ किया जा रहा है क्योंकि हतोत्साहित किया जाता है, तो वस्तु ही बाहर यह आंतरिक तुल्यकालन टूट जाएगा से एक ताला के रूप में प्रयोग किया जाता है। साथ ही, याद रखें कि synchronized विधियां this को लॉक के रूप में भी उपयोग कर रही हैं, जो अवांछित प्रभाव का कारण बन सकती है।
  2. ताला final लॉक घोषित करने की सिफारिश की जाती है जिसमें एक स्थिति को रोकने के लिए synchronized ब्लॉक के अंदर एक लॉक ऑब्जेक्ट को फिर से सौंप दिया जाता है, इस प्रकार अलग-अलग धागे विभिन्न लॉक ऑब्जेक्ट्स देखने के लिए होते हैं। यह अन्य प्रश्न देखें: Locking on a mutable object - Why is it considered a bad practice?
+0

+1; आप एक अच्छे उत्तर बैज के लायक हैं :) – GETah

3

जहां thread1 और thread2 पहुँच method1, thread3 और thread4 पहुँच method2 है एक परिदृश्य की कल्पना करें। this पर सिंक्रनाइज़ किया जा रहा thread3 और thread4 को ब्लॉक कर देगा अगर thread1 या thread2method1 एक्सेस कर रहे हैं के रूप में thread3 और thread4method1 कोई लेना देना नहीं है जो नहीं होना चाहिए। इसके लिए एक अनुकूलन पूरे वर्ग के उदाहरण को लॉक करने के बजाय दो अलग-अलग ताले का उपयोग करना है।

सिंक्रनाइज़ बयान भी सुक्ष्म तुल्यकालन के साथ संगामिति में सुधार के लिए उपयोगी होते हैं:

यहाँ एक अच्छा पैरा मैं JavaDoc पर पाया कि इस को दर्शाता है। मान लीजिए, उदाहरण के लिए, कक्षा एमएसएलंच में दो उदाहरण फ़ील्ड, सी 1 और सी 2 हैं, जिनका कभी भी उपयोग नहीं किया जाता है। ये सभी फ़ील्ड अद्यतन सिंक्रनाइज़ किया जाना चाहिए, लेकिन वहाँ लिए कोई कारण नहीं है c2 के एक अद्यतन के साथ interleaved होने से c1 का एक अद्यतन को रोकने के - और ऐसा करने से अनावश्यक बनाने अवरुद्ध

+0

आपके लिए भी +1। ताले का अनाज क्यों होना चाहिए इसका एक अच्छा उदाहरण। – Tudor

0

एक ताला उपयोग करने पर विचार द्वारा संगामिति कम कर देता है java.util.concurrent पैकेज से
यह अधिक अनुकूलित लॉकिंग प्रदान कर सकता है, उदाहरण के लिए - ReadWriteLock का उपयोग करके सभी पाठकों को प्रतीक्षा किए बिना पहुंचने देगी।

0

"ReentrantReadWriteLock" का पूर्ण कार्य उदाहरण यहां दिया गया है।

public class DataReader { 
private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); 
private static final Lock read = readWriteLock.readLock(); 
private static final Lock write = readWriteLock.writeLock(); 
public static void loadData() { 
    try { 
    write.lock(); 
    loadDataFromTheDB()); 
    } finally { 
    write.unlock(); 
    } 
} 

public static boolean readData() { 
    try { 
    read.lock(); 
    readData(); 
    } finally { 
    read.unlock(); 
    } 
} 

public static List loadDataFromTheDB() { 
    List list = new ArrayList(); 
    return list; 
} 

    public static void readData() throws DataServicesException { 
    //Write reading logic 
    } 
}