1. 程式人生 > 實用技巧 >Java 中物件鎖和類鎖的區別?

Java 中物件鎖和類鎖的區別?

一 物件鎖和類鎖的關係

/*
 * 
 物件鎖和【類鎖】 全域性鎖的關係?
        物件鎖是用於物件例項方法,或者一個物件例項上的   this
        類鎖是用於類的靜態方法或者一個類的class物件上的。 Ag.class
        
        我們知道,類的物件例項可以有很多個,但是每個類只有一個class物件,
        所以不同物件例項的物件鎖是互不干擾的,但是每個類只有一個類鎖。
 */

物件鎖, 不同物件。

public class SynchrDemo {
    public static void main(String[] args) {
        
        Thread1 thread1 
= new Thread1(); Thread1 thread2 = new Thread1(); thread1.start(); thread2.start(); } } class Ag{ public void show(){ // this 是當前物件的例項,由於新建兩個物件,不是同一物件。所以這裡是鎖不住的。 程式碼快的方式,比修飾在方法上更細化控制。 synchronized (this) { for (int i = 0; i < 4; i++) { System.out.println(Thread.currentThread().getName()
+ " i=" + i); } } } } class Thread1 extends Thread{ @Override public void run() { //這裡是新建物件 主方法中new了兩個thread,就是new了兩個Ag物件 Ag ag = new Ag(); ag.show(); } }

關鍵字修飾方法

public class SynchrDemo {
    public static void main(String[] args) {
        
        Thread1 thread1 
= new Thread1(); Thread1 thread2 = new Thread1(); thread1.start(); thread2.start(); } } class Ag{ // 這次修飾的是方法,範圍比程式碼塊要大,意味著在這個區域內,鎖生效的時候,都是在阻塞,其他執行緒的等待時間就會增加。 // 這次實驗的非同一物件,所以這裡的鎖是不起作用的。 public synchronized void show(){ for (int i = 0; i < 4; i++) { System.out.println(Thread.currentThread().getName() + " i=" + i); } } } class Thread1 extends Thread{ @Override public void run() { //這裡是新建物件 主方法中new了兩個thread,就是new了兩個Ag物件 Ag ag = new Ag(); ag.show(); } }

二 物件鎖 同一物件

package com.aaa.threaddemo;
/*
 * 一 Java中的關鍵字  synchronized  是啥?
 *         synchronized是Java提供的一個併發控制的關鍵字。
 * 
 *         用法:同步方法 和 同步程式碼塊。
 *              可以修飾方法 也可以  修飾程式碼塊。
 *         
 *         作用: 被synchronized修飾的程式碼塊及方法,在同一時間,只能被單個執行緒訪問。【保證執行緒安全】

    1 修飾方法和程式碼塊有什麼不同?
         二者的結果是一樣的
         
         修飾方法時,作用域是整個方法,控制的範圍大。
     
         synchronized 程式碼塊 可控制具體的作用域,更精準控制提高效率。
         減少阻塞帶來的時間問題。

    2 同步鎖的給誰用的?
        同步鎖基於物件,只要鎖的來源一致,即可達到同步的作用。
        所以,但物件不一樣,則不能達到同步效果。

    3 synchronized修飾方法,程式碼塊,鎖未釋放,此時,其他執行緒呼叫同一物件的其他被synchronized修飾的方法,程式碼塊,會如何?
        當執行緒 A 呼叫某物件的synchronized 方法 或者 synchronized 程式碼塊時,若同步鎖未釋放,
        其他執行緒呼叫同一物件的其他 synchronized 方法 或者 synchronized 程式碼塊時將被阻塞,直至執行緒 A 釋放該物件的同步鎖。(注意:重點是其他)

    4 呼叫非synchronized方法 ,程式碼快呢?
        當執行緒 A 呼叫某物件的synchronized 方法 或者 synchronized 程式碼塊時,無論同步鎖是否釋放,
        其他執行緒呼叫同一物件的其他 非 synchronized 方法 或者 非 synchronized 程式碼塊時可立即呼叫。

    5 全域性鎖如何實現?
        全域性鎖: 鎖住整個 Class,而非某個物件或例項。1-4都是例項鎖
        實現: 靜態 synchronized 方法
        
        static 宣告的方法為全域性方法,與物件例項化無關,
        所以 static synchronized 方法為全域性同步方法,與物件例項化無關。

    6 synchronized 具體 Class 的程式碼塊?
        synchronized (Ag.class) 獲得的同步鎖是全域性的,
        static synchronized 獲得的同步鎖也是全域性的,同一個鎖,所以達到同步效果。

    7 物件鎖和【類鎖】 全域性鎖的關係?
        物件鎖是用於物件例項方法,或者一個物件例項上的   this
        類鎖是用於類的靜態方法或者一個類的class物件上的。 Ag.class
        
        我們知道,類的物件例項可以有很多個,但是每個類只有一個class物件,
        所以不同物件例項的物件鎖是互不干擾的,但是每個類只有一個類鎖。




 * 
 * 
 */

/*
 * 
 物件鎖和【類鎖】 全域性鎖的關係?
        物件鎖是用於物件例項方法,或者一個物件例項上的   this
        類鎖是用於類的靜態方法或者一個類的class物件上的。 Ag.class
        
        我們知道,類的物件例項可以有很多個,但是每個類只有一個class物件,
        所以不同物件例項的物件鎖是互不干擾的,但是每個類只有一個類鎖。
 */


public class SynchrDemo {
    public static void main(String[] args) {
        
        // 改造後,可以確保是同一物件  驗證  synchronized  是否生效
        Ag ag = new Ag();
        
        Thread1 thread1 = new Thread1(ag);
        Thread1 thread2 = new Thread1(ag);
        
        thread1.start();
        thread2.start();

    }
}

class Ag{
    // 這次修飾的是方法,範圍比程式碼塊要大,意味著在這個區域內,鎖生效的時候,都是在阻塞,其他執行緒的等待時間就會增加。
    // 這次實驗的同一物件,所以這裡的鎖是起作用的。
    public synchronized void show(){
            for (int i = 0; i < 4; i++) {
                System.out.println(Thread.currentThread().getName() + " i=" + i);
            }
    }

}

/*
 *   改造一些 物件的生成,確保在Thread1 中獲得的是同一物件
 */
class Thread1 extends Thread{    
    
    private Ag mag;
    
    public  Thread1(Ag ag) {
        mag = ag;
    }
    
    @Override
    public void run() {
        mag.show();
        
    }    
}

驗證程式碼快的方式?

public class SynchrDemo {
    public static void main(String[] args) {
        
        // 改造後,可以確保是同一物件  驗證  synchronized  是否生效
        Ag ag = new Ag();
        
        Thread1 thread1 = new Thread1(ag);
        Thread1 thread2 = new Thread1(ag);
        
        thread1.start();
        thread2.start();

    }
}

class Ag{
    // 這次修飾的是方法,範圍比程式碼塊要大,意味著在這個區域內,鎖生效的時候,都是在阻塞,其他執行緒的等待時間就會增加。
    // 這次實驗的同一物件,所以這裡的鎖是起作用的。
    public  void show(){
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                System.out.println(Thread.currentThread().getName() + " i=" + i);
            }
            
            // this 就是當前的物件,我們現在獲得就是同一物件
            System.out.println(this);
        }
    }

}

/*
 *   改造一些 物件的生成,確保在Thread1 中獲得的是同一物件
 */
class Thread1 extends Thread{    
    
    private Ag mag;
    
    public  Thread1(Ag ag) {
        mag = ag;
    }
    
    @Override
    public void run() {
        mag.show();
        
    }    
}

三 類鎖? 非同一物件

/*
 * 
 * 類鎖,全域性鎖如何實現?
        全域性鎖: 鎖住整個 Class,而非某個物件或例項
        
        實現:   
        1    在靜態方法上用 synchronized 關鍵字修飾
        2    在程式碼塊上使用 類名.class
            
        
        static 宣告的方法為全域性方法,與物件例項化無關,
        所以 static synchronized 方法為全域性同步方法,與物件例項化無關。
 */

public class SynchrDemo {
    public static void main(String[] args) {
        
        //非同一物件
        Thread2 thread1 = new Thread2();
        Thread2 thread2 = new Thread2();
        
        thread1.start();
        thread2.start();

    }
}

class Ag{
    public  void show(){
        // 使用 synchronized()  方法,將鎖控制在程式碼快上。
        synchronized (Ag.class) {
            for (int i = 0; i < 4; i++) {
                System.out.println(Thread.currentThread().getName() + " i=" + i);
            }
            
            // this 就是當前的物件,我們現在獲得就是非同一物件
            System.out.println(this);
        }
    }

}

class Thread2 extends Thread{
    
    @Override
    public void run() {
        Ag ag = new Ag();
        ag.show();
        
    }    
}

測試 關鍵字修飾 static 方法

public class SynchrDemo {
    public static void main(String[] args) {
        
        //非同一物件
        Thread2 thread1 = new Thread2();
        Thread2 thread2 = new Thread2();
        
        thread1.start();
        thread2.start();

    }
}

class Ag{
    // 靜態的方法  被synchronized 修飾後, 鎖住的是 類。
    public static synchronized  void show(){
            for (int i = 0; i < 4; i++) {
                System.out.println(Thread.currentThread().getName() + " i=" + i);
            }            
    }

}

class Thread2 extends Thread{
    
    @Override
    public void run() {
        Ag ag = new Ag();
        ag.show();
        
    }    
}