1. 程式人生 > >11、JUC--線程八鎖

11、JUC--線程八鎖

mda try ima info args ktr this pan oid

線程八鎖

• 一個對象裏面如果有多個synchronized方法,某一個時刻內,只要一個線程去調用
  其中的一個synchronized方法了,其它的線程都只能等待,換句話說,某一個時刻
  內,只能有唯一一個線程去訪問這些synchronized方法


• 鎖的是當前對象this,被鎖定後,其它的線程都不能進入到當前對象的其它的
  synchronized方法


• 加個普通方法後發現和同步鎖無關


• 換成兩個對象後,不是同一把鎖了,情況立刻變化。


• 都換成靜態同步方法後,情況又變化


• 所有的非靜態同步方法用的都是同一把鎖——實例對象本身,也就是說如果一個實

  例對象的非靜態同步方法獲取鎖後,該實例對象的其他非靜態同步方法必須等待獲
  取鎖的方法釋放鎖後才能獲取鎖,可是別的實例對象的非靜態同步方法因為跟該實
  例對象的非靜態同步方法用的是不同的鎖,所以毋須等待該實例對象已獲取鎖的非
  靜態同步方法釋放鎖就可以獲取他們自己的鎖。


• 所有的靜態同步方法用的也是同一把鎖——類對象本身,這兩把鎖是兩個不同的對
  象,所以靜態同步方法與非靜態同步方法之間是不會有競態條件的。但是一旦一個
  靜態同步方法獲取鎖後,其他的靜態同步方法都必須等待該方法釋放鎖後才能獲取
  鎖,而不管是同一個實例對象的靜態同步方法之間,還是不同的實例對象的靜態同

  步方法之間,只要它們同一個類的實例對象!

題目判打印的是one還是two?

1、

class Number{
    
    public synchronized void getOne(){
        System.out.println("one");
    }
    
    public synchronized void getTwo(){
        System.out.println("two");
    }
    
}

測試:

public static void main(String[] args) {
    
        Number num 
= new Number(); new Thread(new Runnable() { @Override public void run() { num.getOne(); } }).start(); new Thread(new Runnable() { @Override public void run() { num.getTwo(); } }).start(); }

兩個普通同部方法,兩個線程標準打印

技術分享圖片

2、

新增方法讓getOne方法讓其睡眠三秒

class Number{
    
    public synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("one");
    }
    
    public synchronized void getTwo(){
        System.out.println("two");
    }
    
}

新增Thread.sleep()方法給getOne()

此時得到結果的順序:

技術分享圖片

3、

新增一個普通方法

class Number{
    
    public synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("one");
    }
    
    public synchronized void getTwo(){
        System.out.println("two");
    }
    
    public void getThree(){
        System.out.println("Three");
    }
    
}

測試類:

Number num = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                num.getOne();
            }
        }).start();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                num.getTwo();
            }
        }).start();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                num.getThree();
            }
        }).start();

技術分享圖片

4、

兩個普通同部方法,兩個Number對象

class Number{
    
    public synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    
    public synchronized void getTwo(){
        System.out.println("two");
    }
    
    public void getThree(){
        System.out.println("Three");
    }
}

     Number num = new Number();
        Number num1 = new Number();
        new Thread(new Runnable() {
            @Override
            public void run() {
                num.getOne();
            }
        }).start();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                num1.getTwo();
            }
        }).start();

技術分享圖片

5、

修改getOne()為靜態同部方法

class Number{
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("one");
    }
    
    public synchronized void getTwo(){
        System.out.println("two");
    }
    
    public void getThree(){
        System.out.println("Three");
    }
    
}
        Number num = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                num.getOne();
            }
        }).start();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                num.getTwo();
            }
        }).start();

技術分享圖片

6、

修改兩個方法均為靜態同部方法

class Number{
    
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("one");
    }
    
    public static synchronized void getTwo(){
        System.out.println("two");
    }
}

        Number num = new Number();
        //Number num1 = new Number();
        new Thread(new Runnable() {
            @Override
            public void run() {
                num.getOne();
            }
        }).start();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                num.getTwo();
            }
        }).start();

技術分享圖片

7、

一個靜態同部方法

一個非靜態同部方法

兩個對象

class Number{
    
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    
    public  synchronized void getTwo(){
        System.out.println("two");
    }
    
    public void getThree(){
        System.out.println("Three");
    }
    
}

     Number num = new Number();
        Number num1 = new Number();
        new Thread(new Runnable() {
            @Override
            public void run() {
                num.getOne();
            }
        }).start();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                num1.getTwo();
            }
        }).start();

技術分享圖片

8、

兩個靜態同部方法

兩個對象

class Number{
    
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    
    public static  synchronized void getTwo(){
        System.out.println("two");
    }
}

        Number num = new Number();
        Number num1 = new Number();
        new Thread(new Runnable() {
            @Override
            public void run() {
                num.getOne();
            }
        }).start();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                num1.getTwo();
            }
        }).start();

技術分享圖片

線程八鎖的關鍵:

1、非靜態方法的鎖默認為this,靜態方法的鎖為對應的Class實例

2、在某一個時刻內,只能有一個線程持有鎖,無論幾個線程

11、JUC--線程八鎖