同步塊中對象級別的鎖和類級別的鎖 —— Thread synchronization, object level locking and class level locking


Java supports multiple threads to be executed. This may cause two or more threads to access the same fields or objects. Synchronization is a process which keeps all concurrent threads in execution to be in synch. Synchronization avoids memory consistence errors caused due to inconsistent view of shared memory. When a method is declared as synchronized; the thread holds the monitor for that method’s object If another thread is executing the synchronized method, your thread is blocked until that thread releases the monitor.

Synchronization in java is achieved using synchronized keyword. You can use synchronized keyword in your class on defined methods or blocks. Keyword can not be used with variables or attributes in class definition.

Object level locking

Object level locking is mechanism when you want to synchronize a non-static method or non-static code block such that only one thread will be able to execute the code block on given instance of the class. This should always be done to make instance level data thread safe. This can be done as below :

理解:對象級別的鎖:在給定一個對象的情況下,只有一個線程能夠執行代碼塊。用來保護對象級別數據的線程安全

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
        }
    }
}

Class level locking

Class level locking prevents multiple threads to enter in synchronized block in any of all available instances on runtime. This means if in runtime there are 100 instances of  DemoClass, then only one thread will be able to execute demoMethod() in any one of instance at a time, and all other instances will be locked for other threads. This should always be done to make static data thread safe.

理解:類級別鎖:避免多個線程進入每一個實例的同步塊。假如DemoClass有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
        }
    }
}


Let's say you have two different instances of the same class, who need to update some static field when they do work. In this case, you will have to use the class to synchronize on, because the static field is shared between instances: 

public class Example {
  private static int n;
 
  public void doStuff() {
    // do some stuff
     
    synchronized(Example.class) {
      n++;
    }
  }
}

In this code, n keeps track of how often doStuff is called, no matter on which instance it is called on. In order to update n, you need to make sure that no other thread accesses it at the same time. Because n is shared between different instances, you can't use synchronized(this), you have to use a lock that is also shared between different instances. In this case, we use Example.class, which we can be quite certain will be shared between all instances of Example. 
Note that it doesn't matter what lock you use to synchronize on, as long as it is the same lock for all instances. We could also have used Object.class (which is also visible to all instances of Example) or even String.class or some static Object field in Example: 

public class Example {
  private static int n;
  private static final Object lock = new Object();
 
  ...
 
    synchronized(lock) {
      n++;
    }
 
  ...
}

Note that using the current class (Example.class in this case) is just the standard way of doing things.

理解:當你需要保護類級別的數據的時候,就需要用類級別的鎖或者是鎖住類級別的數據。


 


 

The snippet synchronized(X.class) uses the class instance as a monitor. As there is only one class instance (the object representing the class metadata at runtime) one thread can be in this block.

With synchronized(this) the block is guarded by the instance. For every instance only one thread may enter the block.

synchronized(X.class) is used to make sure that there is exactly one Thread in the block(只有一個線程)synchronized(this) ensures that there is exactly one thread per instance(每個實例中有一個線程). If this makes the actual code in the block thread-safe depends on the implementation. If mutate only state of the instance synchronized(this) is enough.



 A synchronized method acquires a monitor (§17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.



 

Some Important notes

  1. Synchronization in java guarantees that no two threads can execute a synchronized method which requires same lock simultaneously or concurrently.
  2. synchronized keyword can be used only with methods and code blocks. These methods or blocks can be static or non-static both.
  3. When ever a thread enters into java synchronized method or block it acquires a lock and whenever it leaves java synchronized method or block it releases the lock. Lock is released even if thread leaves synchronized method after completion or due to any Error or Exception.
  4. java synchronized keyword is re-entrant in nature it means if a java synchronized method calls another synchronized method which requires same lock then current thread which is holding lock can enter into that method without acquiring lock.
  5. Java Synchronization will throw NullPointerException if object used in java synchronized block is null. For example, in above code sample if lock is initialized as null, the synchronized (lock) will throw NullPointerException.
  6. Synchronized methods in Java put a performance cost on your application. So use synchronization when it is absolutely required. Also, consider using synchronized code blocks for synchronizing only critical section of your code.
  7. It’s possible that both static synchronized and non static synchronized method can run simultaneously or concurrently because they lock on different object.
  8. According to the Java language specification you can not use java synchronized keyword with constructor it’s illegal and result in compilation error.
  9. Do not synchronize on non final field on synchronized block in Java. because reference of non final field may change any time and then different thread might synchronizing on different objects i.e. no synchronization at all. Best is to use String class, which is already immutable and declared final.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM