1. 程式人生 > >java鎖學習(一)

java鎖學習(一)

作用

能夠保證同一時刻,最多隻有一個執行緒執行該段程式碼,以達到併發安全的效果

主要用於同時刻對執行緒間對任務進行鎖

地位

synchronized是JAVA的原生關鍵字,是JAVA中最基本的互斥手段,是併發程式設計中的元老角色

不使用併發的後果

不使用併發會導致多執行緒情況下,同一個資料被多個執行緒同時更改,造成結果和預期不一致導致蟲子的出生(bug)。

class MissRequestNumAsync implements Runnable {
    static public int i = 0;
    @Override
    public void run() {
        for (int j = 0; j < 100000; j ++) {
            i++;
        }
    }
}

public class SynchronizedObjectAction{
    static MissRequestNumAsync m1 = new MissRequestNumAsync();

   public static void main(String[] args) {
        System.out.println("消失的請求數-不使用併發的後果");

        //消失的請求數
        Thread t1 = new Thread(m1);
        Thread t2 = new Thread(m1);
        t1.start();
        t2.start();
		 System.out.println(MissRequestNumAsync.i);
	}
}

執行結果(並且每次都不一樣)

消失的請求數-不使用併發的後果
102171

鎖的分類

  1. 物件鎖(方法鎖、同步程式碼塊鎖)
  2. 類鎖(靜態鎖、class物件)

物件鎖

同步程式碼塊鎖

直接擼

//程式碼塊鎖
//劣勢:太多鎖會增加業務複雜度
//解決方式: 成熟的工具類
//除錯:  thread.getStats();
class SyncObjArea implements Runnable{
    static public int i = 0;
    Object sleepLock1 = new Object();
    Object sleepLock2 = new Object();
    @Override
    public void run() {
        //這裡有搶佔機制
        synchronized (sleepLock1) {
            System.out.println("我是同步程式碼塊鎖1");
            try{
                Thread.sleep(3000);
            }catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"執行結束");
        }
        //這裡有搶佔機制
        synchronized (sleepLock2) {
            System.out.println("我是同步程式碼塊鎖2");
            try{
                Thread.sleep(3000);
            }catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"執行結束");
        }
    }
}

執行結果(多次執行,結果不一)

我是同步程式碼塊鎖1
Thread-2執行結束
我是同步程式碼塊鎖2
我是同步程式碼塊鎖1
Thread-3執行結束
Thread-2執行結束
我是同步程式碼塊鎖2
Thread-3執行結束
同步程式碼塊執行緒執行完畢

方法鎖

方法鎖預設是物件級別的(this)

//方法鎖
class SyncObjMethod implements Runnable {
    static public int i = 0;
    @Override
    public void run() {
      method();
    }

    public synchronized void method(){
        System.out.println("我是方法鎖");
        try{
            Thread.sleep(3000);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"執行結束");
    }
}

執行結果

我是方法鎖
Thread-4執行結束
我是方法鎖
Thread-5執行結束
方法鎖形式  執行緒執行完畢

原始碼位置

執行緒學習