併發程式設計系列(三) synchronized內建鎖

2021-09-14 04:43:30 字數 4086 閱讀 5585

synchronized可以對類或者物件加鎖,從而保證多個執行緒在同乙個時刻只有乙個執行緒執行被synchronized修飾的**。

例子(簡單的購票**):

現在設計乙個普通的購票場景,乙個票務處,五個客戶同時在票務處買票:

1).票務處(ticketmanager):

/**

* 票務處類

* @classname: ticketmanager

* @description: 票務處類

* @author: vincentho

* @date: 2023年3月30日 下午12:38:36

*/public

class

ticketmanager

public

ticketmanager

(int ticketnum)

}

2).購票客戶(buyticketclient)

/**

* 購票客戶

* @classname: buyticketclient

* @description: 購票客戶

* @author: vincentho

* @date: 2023年3月30日 下午12:39:40

*/public

class

buyticketclient

extends

thread

@override

public

void

run(

)}

3).測試主類(buyticketmain)

/**

* 主類

* @classname: buyticketmain

* @description: 主類

* @author: vincentho

* @date: 2023年3月30日 下午12:41:30

*/public

class

buyticketmain

}}

結果:

thread-0得到票,餘票:2

thread-4得到票,餘票:0

thread-3得到票,餘票:1

thread-2得到票,餘票:2

thread-1得到票,餘票:2

如上所示,這結果很明顯不是我們想看到的。五個人同時買票,餘票應該從5到0,而不應該這樣混亂。這就是因為五個執行緒,同時操作乙個資源導致的後果,那麼下面如果在buyticket()方法中加入synchronized鎖,再看看結果如何:

/**

* 票務處類

* @classname: ticketmanager

* @description: 票務處類

* @author: vincentho

* @date: 2023年3月30日 下午12:38:36

*/public

class

ticketmanager

}public

ticketmanager

(int ticketnum)

}

結果:

thread-0得到票,餘票:4

thread-4得到票,餘票:3

thread-3得到票,餘票:2

thread-2得到票,餘票:1

thread-1得到票,餘票:0

如上所示,得出了我們想要的結果,這就是synchronized鎖的作用

如果synchronized不是鎖在靜態方法上,那麼都是屬於物件鎖。物件鎖鎖住的是物件,只要是屬於同乙個物件,那麼多個執行緒是不能同時進行的(像上面的購票例子就是物件鎖)

例子:

public

class

instancesync

catch

(exception e)

}}

public

class

instancesynctest

@override

public

void

run()}

public

static

void

main

(string[

] args)

}

執行結果:

thread-1------執行開始

thread-0------執行開始

執行物件鎖方法。。。

執行物件鎖方法。。。

thread-0------執行結束

thread-1------執行結束

從結果可以看出,兩個執行緒是同步進行的。那麼假如操作的是同乙個物件,結果會如何呢,下面改一下測試類的**:

public

class

instancesynctest

@override

public

void

run()}

public

static

void

main

(string[

] args)

}

結果:

thread-0------執行開始

thread-1------執行開始

執行物件鎖方法。。。

thread-0------執行結束

執行物件鎖方法。。。

thread-1------執行結束

建立執行緒物件的時候如果傳入同乙個物件,兩個執行緒操作同乙個物件,那麼執行緒就不能同時執行了。這就是因為synchronized在這裡是對物件上鎖,所以只要是不同的物件,就不會被鎖住。

延申:如果說這是鎖住乙個物件的,那麼假如乙個類有多個sychronized修飾的方法,那麼結果會怎麼樣呢?改一下上面的方法:

public

class

instancesync

catch

(exception e)

}public

synchronized

void

other()

catch

(exception e)

}}

public

class

instancesynctest

@override

public

void

run()}

class

testthread2

extends

thread

@override

public

void

run()}

public

static

void

main

(string[

] args)

}

注意上面的例子是開啟了兩個執行緒,分別呼叫了同乙個物件的兩個有synchronized的方法,那麼結果是:

thread-0------執行開始

thread-1------執行開始

執行物件鎖方法。。。

thread-0------執行結束

rbq rbq。。。

thread-1------執行結束

結果就是執行緒阻塞呼叫方法,和多執行緒呼叫同乙個物件同乙個方法是乙個結果。這就是物件鎖的作用。

synchronized如果在static方法上,那麼這個synchronized的範圍就是這個類,也就是類鎖,它鎖的是這個類的class物件。而在jvm中,class物件是放在永久代(元空間)中的,所以class物件是唯一的,所以多少個執行緒,操作這個類多少個物件,呼叫這個方法的時候都是會被阻塞的。

**注意:**如果乙個類裡面,類鎖和物件鎖同時都有,兩個執行緒分別呼叫這個類鎖的方法和物件鎖的方法,也是可以同時執行的,因為分別所的是類的class物件和例項物件

Java的高併發程式設計系列(三)

鎖定某物件o,如果o的屬性發生改變,不影響鎖的使用,但是如果o變成另外乙個物件,則鎖定的物件發生改變,應該避免將鎖定物件的引用變成另外乙個物件。public class demo17 catch interruptedexception e system.out.println thread.cur...

併發程式設計(三)

不可變物件只要發布了,一定是執行緒安全的。滿足什麼條件是不可變物件?如何建立乙個不可變物件?public static mapunmodifiablemap map extends k,extends v m serial include private static class unmodifia...

Java併發程式設計系列 CountDownLatch

countdownlatch簡介 countdownlatch是基於aqs實現的乙個執行緒同步工具,也稱為閉鎖。它的作用是讓乙個或者多個執行緒等待某個事件的發生。簡單的理解為countdownlatch有乙個正數計數器,countdown方法對計數器做減操作,await方法等待計數器達到0。所有aw...