2010-09-15 17 views
14

यदि कोई थ्रेड टी 1 क्लास लेवल लॉक प्राप्त करके एक विधि एम 1 में प्रवेश करता है, तो क्या इसका मतलब है कि एक और थ्रेड टी 2 ऑब्जेक्ट लेवल लॉक प्राप्त करके एक अलग विधि एम 2 नहीं चला सकता है?जावा क्लास लेवल लॉक बनाम ऑब्जेक्ट लेवल लॉक

उत्तर

38

नहीं, इसका मतलब यह नहीं है। "क्लास लेवल लॉक" एक अलग ऑब्जेक्ट पर एक नियमित लॉक है, अर्थात् SomeClass.classthis पर "ऑब्जेक्ट लेवल लॉक" लॉक।

संपादित करें:

public class SomeClass { 
    public synchronized static void m1() { 
     //do something 
    } 

    public synchronized void m2() { 
     //do something 
    } 
} 

और जवाब: बस के रूप में वे नीचे परिभाषित कर रहे हैं, तो एम 1 और एम 2 समवर्ती चलाया जा सकता है यकीन है कि मैं शब्दावली की अपनी समझ अनुसरण कर रहा हूँ, आप सोच रहे हैं बनाने के लिए हाँ है, एम 1 और एम 2 समवर्ती रूप से चलाया जा सकता है। यह कार्यात्मक इस के बराबर है:

public class SomeClass { 
    public static void m1() { 
     synchronized (SomeClass.class) { 
      //do something 
     } 
    } 
    public void m2() { 
     synchronized (this) { 
      //do something 
     } 
    } 
} 

के बाद से वे पूरी तरह से विभिन्न वस्तुओं पर सिंक्रनाइज़ कर रहे हैं, वे परस्पर अनन्य नहीं हैं।

+1

क्या होगा यदि दोनों विधियों को स्थैतिक घोषित किया गया हो? मुझे विश्वास है कि उस मामले में, दोनों पारस्परिक रूप से अनन्य हो जाएंगे, क्या यह सही है? – buch11

+2

@ buch11: यह सही है, ऐसा लगता है कि दोनों सिंक्रनाइज़ (कुछ क्लास.क्लास) {...} 'कर रहे थे, और किसी भी जटिल क्लासलोडिंग परिदृश्य को छोड़कर, यह दोनों मामलों में एक ही वस्तु होगी। तकनीकी रूप से, क्लासलोडिंग आपको एक ही कक्षा के दो अलग "लोडिंग" की अनुमति देता है, और आप समानांतर में इस तरह के विभिन्न वर्गों में स्थिर सिंक्रनाइज़ विधियों को चला सकते हैं। लेकिन उस अजीबता को छोड़कर, यह पारस्परिक रूप से अनन्य है। –

+0

आपको आश्चर्य हो सकता है कि एक स्थिर सिंक्रनाइज़ विधि कब लागू की जाती है, क्योंकि एक स्थिर विधि कक्षा से जुड़ी होती है, न कि ऑब्जेक्ट। इस मामले में, धागे कक्षा से जुड़े कक्षा वस्तु के लिए आंतरिक लॉक प्राप्त करता है। ** इस प्रकार कक्षा के स्थैतिक क्षेत्रों तक पहुंच को लॉक द्वारा नियंत्रित किया जाता है जो कक्षा के किसी भी उदाहरण के लिए लॉक से अलग होता है। ** [स्रोत] (https://docs.oracle.com/javase/tutorial/essential/concurrency /locksync.html) – Eduardo

6

जावा में ताले के दो प्रकार हैं:

  1. कक्षा स्तर
  2. वस्तु स्तर

स्टेटिक तरीकों के मामले में ताला हमेशा वर्ग पर लेकिन उदाहरण के मामले में चेक किया गया है ऑब्जेक्ट पर ताला हमेशा जांच की जाती है।

उदाहरण:

show1()गैर स्थिर और show() है स्थिर है। अब, show() कक्षा नाम (या ऑब्जेक्ट द्वारा) और show1() ऑब्जेक्ट द्वारा बुलाया जाता है, तो दोनों विधियों को एक साथ दो धागे तक पहुंचा जा सकता है।

class Shared{ 
    static int x; 
    static synchronized void show(String s,int a){ 
     x=a; 
     System.out.println("Starting in method "+s+" "+x); 
     try{ 
      Thread.sleep(2000); 
     } 
     catch(Exception e){ } 
     System.out.println("Ending from method "+s+" "+x); 
    } 
    synchronized void show1(String s,int a){ 
     x=a; 
     System.out.println("Starting show1 "+s); 
     try{ 
      Thread.sleep(2000); 
     } 
     catch(Exception e){ } 
     System.out.println("Ending from show1 "+s); 
    } 
} 
class CustomThread extends Thread{ 
    Shared s; 
    public CustomThread(Shared s,String str){ 
     super(str); 
     this.s=s; 
     start(); 
    } 
    public void run(){ 
     Shared.show(Thread.currentThread().getName(),10); 
    } 
} 
class CustomThread1 extends Thread{ 
    Shared s; 
    public CustomThread1(Shared s,String str){ 
     super(str); 
     this.s=s; 
     start(); 
    } 
    public void run(){ 
     s.show1(Thread.currentThread().getName(),20); 
    } 
} 
public class RunSync { 
    public static void main(String[] args) { 
     Shared sh=new Shared(); 
     CustomThread t1=new CustomThread(sh,"one"); 
     CustomThread1 t2=new CustomThread1(sh,"two"); 
    } 
} 

आउटपुट:

Starting in method one 10 
Starting show1 two 
Ending from method one 20 
Ending from show1 two   
12

वस्तु स्तर लॉकिंग:

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

public class DemoClass 
{ 
    public synchronized void demoMethod(){} 
} 

or 

public class DemoClass 
{ 
    public void demoMethod(){ 
    synchronized (this) 
    { 
    //other thread safe code 
    } 
} 
} 

or 

public class DemoClass 
{ 
    private final Object lock = new Object(); 
    public void demoMethod(){ 
    synchronized (lock) 
{ 
    //other thread safe code 
} 
} 

कक्षा के स्तर का ताला:

कक्षा के स्तर का ताला से अधिक थ्रेड क्रम पर सभी उपलब्ध उदाहरणों में से किसी में सिंक्रनाइज़ ब्लॉक में प्रवेश करने के लिए रोकता है। इसका अर्थ यह है कि यदि रनटाइम में डेमो क्लास के 100 उदाहरण हैं, तो केवल एक ही थ्रेड एक समय में किसी भी एक में demoMethod() निष्पादित करने में सक्षम होगा, और अन्य सभी उदाहरण अन्य थ्रेड के लिए लॉक हो जाएंगे। स्थिर डेटा थ्रेड को सुरक्षित बनाने के लिए यह हमेशा किया जाना चाहिए।

public class DemoClass 
{ 
    public synchronized static void demoMethod(){} 
} 

or 

public class DemoClass 
{ 
    public void demoMethod(){ 
    synchronized (DemoClass.class) 
    { 
    //other thread safe code 
    } 
} 
} 

or 

public class DemoClass 
{ 
private final static Object lock = new Object(); 
public void demoMethod(){ 
synchronized (lock) 
    { 
    //other thread safe code 
    } 
} 
} 
2

उदाहरण जावा में वस्तु और कक्षा स्तर ताले को समझने के लिए

1) ऑब्जेक्ट स्तर ताला उदाहरण

package com.test; 

public class Foo implements Runnable { 

    @Override 
    public void run() { 
     Lock(); 
    } 
    public void Lock() { 
     System.out.println(Thread.currentThread().getName()); 
     synchronized(this) { 
      System.out.println("in block " + Thread.currentThread().getName()); 
      System.out.println("in block " + Thread.currentThread().getName() + " end"); 
     } 
    } 

    public static void main(String[] args) { 
     Foo b1 = new Foo(); 
     Thread t1 = new Thread(b1); 
     Thread t2 = new Thread(b1);    
     Foo b2 = new Foo(); 
     Thread t3 = new Thread(b2);    
     t1.setName("t1"); 
     t2.setName("t2"); 
     t3.setName("t3");    
     t1.start(); 
     t2.start(); 
     t3.start(); 
    } 
} 

उत्पादन:

t1 
    t3 
    t2 
    in block t3 
    in block t1 
    in block t3 end 
    in block t1 end 
    in block t2 

ध्यान दें कि थ्रेड टी 1 और टी 2 ब्लॉक के दौरान टी 3 ब्लॉक नहीं होगा। क्योंकि ताला इस वस्तु और धागा पर रखा गया है t3 अलग धागा t1 से इस वस्तु, t2 है

2) कक्षा स्तर ताला उदाहरण

वस्तु स्तर ताला में कोड, केवल Foo.class है सिंक्रनाइज़ ब्लॉक में जोड़ा गया। फू क्लास की ऑब्जेक्ट का उपयोग करके सभी थ्रेड बनाए जा रहे हैं अवरुद्ध हो जाएंगे।

package com.test;  
public class Foo implements Runnable {   
    @Override 
    public void run() { 
     Lock(); 
    } 

    public void Lock() { 
     System.out.println(Thread.currentThread().getName()); 
     synchronized(Foo.class) { 
      System.out.println("in block " + Thread.currentThread().getName()); 
      System.out.println("in block " + Thread.currentThread().getName() + " end"); 
     } 
    } 

    public static void main(String[] args) { 
     Foo b1 = new Foo(); 
     Thread t1 = new Thread(b1); 
     Thread t2 = new Thread(b1);    
     Foo b2 = new Foo(); 
     Thread t3 = new Thread(b2);    
     t1.setName("t1"); 
     t2.setName("t2"); 
     t3.setName("t3");    
     t1.start(); 
     t2.start(); 
     t3.start(); 
    } 
} 

उत्पादन:

t1 
t3 
in block t1 
in block t1 end 
t2 
in block t3 
in block t3 end 
in block t2 
in block t2 end 

सिंक्रनाइज़ ब्लॉक एक ही धागे के लिए क्रियान्वित किया जा रहा है।

0

ऐसा नहीं है कि दोनों स्थिर सिंक्रनाइज़ और गैर स्थिर सिंक्रनाइज़ विधि एक साथ या समवर्ती क्योंकि वे विभिन्न वस्तु पर ताला चला सकते हैं संभव है।

Courtesy

1

कक्षा के स्तर का ताला कीवर्ड "स्टैटिक समन्वयित है, जहां वस्तु स्तर के रूप में सिंक्रनाइज़ कीवर्ड द्वारा केवल हासिल की है द्वारा हासिल की है। वस्तु स्तर ताला अलग धागा, जहां के माध्यम से संचालित करने के लिए एक ही वस्तु को प्रतिबंधित करने के हासिल की है क्योंकि किसी ऑब्जेक्ट को संचालित करने के लिए कक्षा स्तर लॉक प्राप्त किया जाता है।

0

श्रेणी स्तर लॉकिंग के विभिन्न तरीके: 1) सार्वजनिक वर्ग DemoClass {

public static synchronized void demoMethod(){ 
    //dosomething 
} 

}

2)

सार्वजनिक वर्ग DemoClass {

public void demoMethod(){ 

    synchronized(DemoClass.class){ 
     //dosomething 
    } 
} 

}

3)

सार्वजनिक वर्ग DemoClass {

private final static Object lock = new Object(); 
public void demoMethod(){ 

    synchronized(lock){ 
     //dosomething 
    } 
} 

}

+0

यह प्रश्न का उत्तर कैसे देता है? – shmosel

0

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

लेकिन यदि कोई धागा कक्षा स्तर लॉक प्राप्त करता है तो दूसरा धागा इसके उदाहरण में लॉक प्राप्त कर सकता है। 1true

सभी किसी भी विराम के बिना तुरन्त मुद्रित हो जाएगी Instance2 कक्षा उदाहरण -: दोनों काम कर सकते हैं parallel.`

package lock; 

class LockA implements Runnable { 
    @Override 
    public void run() { 
     synchronized (LockA.class) { 
      System.out.println("Class"); 
      try { 
       Thread.sleep(60 * 1000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
public class TestClassVsInstanceLock { 
    public static void main(String[] args) { 
     final LockA a = new LockA(); 
     final LockA b = new LockA(); 
     try { 
      Thread t = new Thread(a); 
      Thread t1 = new Thread() { 
       @Override 
       public void run() { 
        synchronized (b) { 
         System.out.println("Instance 1"+ currentThread().currentThread().holdsLock(b)); 
         try { 
          Thread.sleep(10 * 1000); 
         } catch (InterruptedException e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      }; 
      t.start(); 
      t1.start(); 
      synchronized (a) { 
       System.out.println("Instance2"); 
       Thread.sleep(10 * 1000); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

`

यह प्रिंट होगा।

2

यदि कोई थ्रेड टी 1 कक्षा स्तर लॉक प्राप्त करके एक विधि एम 1 में प्रवेश करता है, तो क्या इसका मतलब है कि एक और थ्रेड टी 2 ऑब्जेक्ट लेवल लॉक प्राप्त करके एक अलग विधि m2 नहीं चला सकता है?

ऑब्जेक्ट लेवल लॉक और क्लास लेवल लॉक अलग हैं। उपरोक्त मामले में, टी 2 ऑब्जेक्ट लेवल लॉक प्राप्त करके विधि एम 2 चला सकता है। लेकिन अगर एम 2 static synchronized है, तो टी 2 एम 2 विधि का आह्वान नहीं कर सकता है जब तक कि टी 1 विधि एम 1 पर कक्षा स्तर लॉक जारी न करे।

Object level lock:

यह एक ही वस्तु पर synchronized तरीकों में से दो आमंत्रण बिछा करने के लिए संभव नहीं है। जब एक थ्रेड किसी ऑब्जेक्ट के लिए synchronized विधि निष्पादित कर रहा है, तो अन्य सभी थ्रेड जो ऑब्जेक्ट के साथ पहले थ्रेड किए जाने तक उसी ऑब्जेक्ट ब्लॉक (निष्पादन को निलंबित) के लिए synchronized विधियों का आह्वान करते हैं।

मान लें कि आप दो synchronized तरीकों एम 1 और वस्तु ओ पर एम 2 है कि धागा T1 विधि एम 1 के निष्पादन के बीच में है, तो धागा टी 2, जब तक कि धागा T1 रिलीज ताला एक ही वस्तु हे पर विधि एम 2 कॉल करने के लिए इंतजार करना पड़ता है विधि एम 1 पर।

Class level lock:

थ्रेड वर्ग के साथ जुड़े Class वस्तु के लिए आंतरिक ताला प्राप्त कर लेता है। इस प्रकार कक्षा के static फ़ील्ड तक पहुंच को लॉक द्वारा नियंत्रित किया जाता है जो कक्षा के किसी भी उदाहरण के लिए लॉक से अलग होता है।

मान लें कि विधि m1 static synchrnozed है और विधि m2 भी static synchronized है और आपके पास दो अलग-अलग ऑब्जेक्ट्स ओ 1 और ओ 2 हैं।

यदि थ्रेड टी 1 ऑब्जेक्ट ओ 1 पर विधि एम 1 के निष्पादन के मध्य में है, तो थ्रेड टी 2 को ऑब्जेक्ट ओ 2 पर कॉल विधि एम 2 तक प्रतीक्षा करना है जब तक कि विधि m1 पर थ्रेड टी 1 रिलीज लॉक न हो।

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