java多線程編程之Synchronized關(guān)鍵字詳解
本文介紹JAVA多線程中的synchronized關(guān)鍵字作為對(duì)象鎖的一些知識(shí)點(diǎn)。
所謂對(duì)象鎖,就是就是synchronized 給某個(gè)對(duì)象 加鎖。關(guān)于 對(duì)象鎖 可參考:這篇文章
一、分析
synchronized可以修飾實(shí)例方法,如下形式:
public class MyObject {
synchronized public void methodA() {
//do something....
}
這里,synchronized 關(guān)鍵字鎖住的是當(dāng)前對(duì)象。這也是稱(chēng)為對(duì)象鎖的原因。
為啥鎖住當(dāng)前對(duì)象?因?yàn)?methodA()是個(gè)實(shí)例方法,要想執(zhí)行methodA(),需要以 對(duì)象.方法() 的形式進(jìn)行調(diào)用(obj.methodA(),obj是MyObject類(lèi)的一個(gè)對(duì)象,synchronized就是把obj這個(gè)對(duì)象加鎖了)。
上面代碼也可寫(xiě)成這樣:
public class MyObject {
public void methodA() {
synchronized(this){
//do something....
}
}
二、特點(diǎn)
使用synchronized關(guān)鍵字同步一個(gè)明顯的特點(diǎn)是:MyObject類(lèi)中定義有多個(gè)synchronized修飾的實(shí)例方法時(shí),若多個(gè)線程擁有同一個(gè)MyObject類(lèi)的對(duì)象,則這些方法只能以同步的方式執(zhí)行。即,執(zhí)行完一個(gè)synchronized修飾的方法后,才能執(zhí)行另一個(gè)synchronized修飾的方法。
如下:
public class MyObject {
synchronized public void methodA() {
//do something....
}
synchronized public void methodB() {
//do some other thing
}
}
MyObject類(lèi)中有兩個(gè)synchronized修飾的方法。
public class ThreadA extends Thread {
private MyObject object;
//省略構(gòu)造方法
@Override
public void run() {
super.run();
object.methodA();
}
}
線程A執(zhí)行methodA()
public class ThreadB extends Thread {
private MyObject object;
//省略構(gòu)造方法
@Override
public void run() {
super.run();
object.methodB();
}
}
線程B執(zhí)行methodB()
public class Run {
public static void main(String[] args) {
MyObject object = new MyObject();
//線程A與線程B 持有的是同一個(gè)對(duì)象:object
ThreadA a = new ThreadA(object);
ThreadB b = new ThreadB(object);
a.start();
b.start();
}
}
由于線程A和線程B持有同一個(gè)MyObject類(lèi)的對(duì)象object,盡管這兩個(gè)線程需要調(diào)用不同的方法,但是必須是同步的,比如:線程B需要等待線程A執(zhí)行完了methodA()方法之后,它才能執(zhí)行methodB()方法。
三、結(jié)論
從上可以看出,本文中講述的 synchronized 鎖的范圍是整個(gè)對(duì)象。如果一個(gè)類(lèi)中有多個(gè)synchronized修飾的同步方法,且多個(gè)線程持有該類(lèi)的同一個(gè)對(duì)象(該類(lèi)的相同的對(duì)象),盡管它們調(diào)用不同的方法,各個(gè)方法的執(zhí)行也是同步的。
如果各個(gè)同步的方法之間沒(méi)有共享變量,或者說(shuō)各個(gè)方法之間沒(méi)有聯(lián)系,但也只能同步執(zhí)行,這會(huì)影響效率。
四、應(yīng)用--使用synchronized避免 因數(shù)據(jù)不一致性而導(dǎo)致讀臟數(shù)據(jù)的情況
如下示例:
public class MyObject {
private String userName = "b";
private String passWord = "bb";
synchronized public void methodA(String userName, String passWord) {
this.userName = userName;
try{
Thread.sleep(5000);
}catch(InterruptedException e){
}
this.passWord = passWord;
}
synchronized public void methodB() {
System.out.println("userName" + userName + ": " + "passWord" + passWord);
}
}
methodA()負(fù)責(zé)更改用戶名和密碼。在現(xiàn)實(shí)中,一個(gè)用戶名對(duì)應(yīng)著一個(gè)密碼。
methodB()負(fù)責(zé)讀取用戶名和密碼。
如果methodB()沒(méi)有用synchronized 修飾,線程A在調(diào)用methodA()執(zhí)行到第7行,更改了用戶名,因某種原因(比如在第9行睡眠了)放棄了CPU。
此時(shí),如果線程B去執(zhí)行methodB(),那么讀取到的用戶名是線程A更改了的用戶名("a"),但是密碼卻是原來(lái)的密碼("bb")。因?yàn)?,線程A睡眠了,還沒(méi)有來(lái)得及更改密碼。
但是,如果methodB()用synchronized修飾,那么線程B只能等待線程A執(zhí)行完畢之后(即改了用戶名,也改了密碼),才能執(zhí)行methodB讀取用戶名和密碼。因此,就避免了數(shù)據(jù)的不一致性而導(dǎo)致的臟讀問(wèn)題。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)java程序設(shè)計(jì)有所幫助。
相關(guān)文章
SpringBoot登錄判斷過(guò)程代碼實(shí)例
這篇文章主要介紹了SpringBoot登錄判斷代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
JavaWeb中轉(zhuǎn)發(fā)與重定向的區(qū)別小結(jié)
轉(zhuǎn)發(fā)和重定向是JavaWeb中常用的兩種頁(yè)面跳轉(zhuǎn)方式,它們?cè)趯?shí)現(xiàn)上有一些區(qū)別,本文主要介紹了JavaWeb中轉(zhuǎn)發(fā)與重定向的區(qū)別小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10
spring?MVC實(shí)現(xiàn)簡(jiǎn)單登錄功能
這篇文章主要為大家詳細(xì)介紹了spring?MVC實(shí)現(xiàn)簡(jiǎn)單登錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09
Springboot+Hutool自定義注解實(shí)現(xiàn)數(shù)據(jù)脫敏
我們?cè)陧?xiàng)目中會(huì)處理敏感數(shù)據(jù)時(shí),通常需要對(duì)這些數(shù)據(jù)進(jìn)行脫敏,本文主要使用了Springboot整合Hutool來(lái)自定義注解實(shí)現(xiàn)數(shù)據(jù)脫敏,感興趣的可以理解下2023-10-10
IDEA配置SpringBoot熱啟動(dòng),以及熱啟動(dòng)失效問(wèn)題
這篇文章主要介紹了IDEA配置SpringBoot熱啟動(dòng),以及熱啟動(dòng)失效問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
SpringBoot Admin 如何實(shí)現(xiàn)Actuator端點(diǎn)可視化監(jiān)控
這篇文章主要介紹了SpringBoot Admin 如何實(shí)現(xiàn)Actuator端點(diǎn)可視化監(jiān)控,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
java 實(shí)現(xiàn)微信服務(wù)器下載圖片到自己服務(wù)器
這篇文章主要介紹了 java 實(shí)現(xiàn)微信服務(wù)器下載圖片到自己服務(wù)器的相關(guān)資料,需要的朋友可以參考下2017-05-05
Java變量的初始化及靜態(tài)方法的實(shí)現(xiàn)
這篇文章主要介紹了Java變量的初始化及靜態(tài)方法的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10

