Synchronized方法鎖、對象鎖、類鎖區別

synchronized關鍵字,咱們通常稱之爲」同步鎖「,用它來修飾須要同步的方法和須要同步代碼塊,默認是當前對象做爲鎖的對象。在修飾類時(或者修飾靜態方法),默認是當前類的Class對象做爲所的對象故存在着方法鎖、對象鎖、類鎖 這樣的概念

一.Synchronized方法鎖(也叫對象鎖)

1.修飾在方法上,多個線程調用同一個對象的同步方法會阻塞,調用不一樣對象的同步方法不會阻塞。(java對象的內存地址是否相同)java

 public synchronized void obj3() {
           int i = 5;
           while (i-- > 0) {
               System.out.println(Thread.currentThread().getName() + " : " + i);
               try {
                   Thread.sleep(500);
               } catch (InterruptedException ie) {
               }
           }
   }

2.修飾代碼塊,這個this就是指當前對象(類的實例),多個線程調用同一個對象的同步方法會阻塞,調用不一樣對象的同步方法不會阻塞。(java對象的內存地址是否相同)多線程

public void obj2() {
       synchronized (this) {
           int i = 5;
           while (i-- > 0) {
               System.out.println(Thread.currentThread().getName() + " : " + i);
               try {
                   Thread.sleep(500);
               } catch (InterruptedException ie) {
               }
           }
       }
   }

3.修飾代碼塊,這個str就是指String對象,多個線程調用同一個對象的同步方法會阻塞,調用不一樣對象的同步方法不會阻塞。(java對象的內存地址是否相同)ide

 public void obj2() {
       String str=new String("lock");//在方法體內,調用一次就實例化一次,多線程訪問不會阻塞,由於不是同一個對象,鎖是不一樣的
       synchronized (str) {
           int i = 5;
           while (i-- > 0) {
               System.out.println(Thread.currentThread().getName() + " : " + i);
               try {
                   Thread.sleep(500);
               } catch (InterruptedException ie) {
               }
           }
       }
   }
public static void main(String[] args) throws InterruptedException {
        test test=new test();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test.obj2();
            }
        }).start();
    
        new Thread(new Runnable() {
            @Override
            public void run() {
                test.obj2();
            }
        }).start();
    }
//兩個方法之間交替執行 沒有阻塞
Thread-0 : 4
Thread-1 : 4
Thread-1 : 3
Thread-0 : 3
Thread-1 : 2
Thread-0 : 2
Thread-1 : 1
Thread-0 : 1
Thread-0 : 0
Thread-1 : 0

共用一個對象,多線程調用obj2同步方法,由於使用的是一個對象鎖,會阻塞。this

String str=new String("lock"); //對象放在方法外,調用方法的時候不會新建立一個對象。
   public void obj2() {
       synchronized (str) {
           int i = 5;
           while (i-- > 0) {
               System.out.println(Thread.currentThread().getName() + " : " + i);
               try {
                   Thread.sleep(500);
               } catch (InterruptedException ie) {
               }
           }
       }
   }

Thread-0 : 4
Thread-0 : 3
Thread-0 : 2
Thread-0 : 1
Thread-0 : 0
Thread-1 : 4
Thread-1 : 3
Thread-1 : 2
Thread-1 : 1
Thread-1 : 0

二.Synchronized類鎖

1.Synchronized修飾靜態的方法spa

  public static synchronized void obj3() {
           int i = 5;
           while (i-- > 0) {
               System.out.println(Thread.currentThread().getName() + " : " + i);
               try {
                   Thread.sleep(500);
               } catch (InterruptedException ie) {
               }
           }
   }

2.synchronized (test.class) ,鎖的對象是test.class,即test類的鎖。線程

  public void obj1() {
        synchronized (test.class) {
           int i = 5;
           while (i-- > 0) {
               System.out.println(Thread.currentThread().getName() + " : " + i);
               try {
                   Thread.sleep(500);
               } catch (InterruptedException ie) {
               }
           }
       }
   }

看完上面的例子,應該能夠分清楚什麼是對象鎖和類鎖了。

那麼問題來了:在一個類中有兩方法,分別用synchronized 修飾的靜態方法(類鎖)和非靜態方法(對象鎖)。多線程訪問兩個方法的時候,線程會不會阻塞?code

 public static synchronized void obj3() {
           int i = 5;
           while (i-- > 0) {
               System.out.println(Thread.currentThread().getName() + " : " + i);
               try {
                   Thread.sleep(500);
               } catch (InterruptedException ie) {
               }
           }
   }

 public synchronized void obj4() {
       int i = 5;
       while (i-- > 0) {
           System.out.println(Thread.currentThread().getName() + " : " + i);
           try {
               Thread.sleep(500);
           } catch (InterruptedException ie) {
           }
       }
   }

答案是???對象

Thread-0 : 4
Thread-1 : 4
Thread-0 : 3
Thread-1 : 3
Thread-1 : 2
Thread-0 : 2
Thread-1 : 1
Thread-0 : 1
Thread-1 : 0
Thread-0 : 0blog

不會阻塞。

總結 

到這麼咱們應該知道了:內存

1,要知足方法同步(或者代碼塊同步)就必須保證多線程訪問的是同一個對象(在java內存中的地址是否相同)。

2,類鎖和對象鎖同時存在時,多線程訪問時不會阻塞,由於他們不是一個鎖。

----------------------------------------------------------------------------------------------------------------

理解不到位的地方,煩請指出來。

相關文章
相關標籤/搜索