国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Java > 正文

Java并發(fā)編程系列(二)----synchronized鎖詳解

2019-11-11 06:42:06
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前面我們分析了volatile關(guān)鍵字,我們知道volatile關(guān)鍵字是無(wú)法保證線程安全的。那么java的線程安全主要由內(nèi)置的synchronized關(guān)鍵字和Locks包下的類來(lái)保證,Locks包下的類留到下一節(jié)再講。

關(guān)于synchronized,有兩種同步方式,一種是同步方法,另外一種是同步代碼塊,關(guān)于什么是同步代碼塊,什么是同步方法就不細(xì)講了,這里主要講講Java的內(nèi)置鎖。看一段代碼

package com.rancho945.concurrent;public class SynchronizedDemo { PRivate Object lockObject = new Object(); //A:同步方法 public synchronized void method1(){ } //B:同步靜態(tài)方法 public static synchronized void method2(){ } public void method3(){ //C:同步代碼塊 synchronized (lockObject) { } } public void method4(){ //D:同步代碼塊 synchronized (this) { } } //E:沒(méi)有同步 public void method5() { }}

很多小伙伴們?nèi)菀装焰i的各種表現(xiàn)形式搞蒙,其實(shí)只要記住兩點(diǎn)即可:

內(nèi)置鎖有兩種:一種是類鎖,另一種是對(duì)象鎖;類鎖只有一個(gè),不同的對(duì)象有不同的對(duì)象鎖。不同的鎖之間不互斥,線程可以并發(fā)執(zhí)行沒(méi)有互斥條件的代碼(廢話)。

看上面的代碼,A、B、C、三處的鎖是不同的,A和D是同一把鎖。A和D處的是SynchronizedDemo對(duì)象鎖,B是Synchronized類鎖,C是lockObject對(duì)象鎖,E沒(méi)有加鎖。

那么也就意味著:多線程可以同時(shí)執(zhí)行ABCE處的代碼,因?yàn)樗麄儧](méi)有互斥條件。而A和D在同一時(shí)刻只能被一個(gè)線程執(zhí)行,因?yàn)樗麄兂钟械氖峭话焰i。

我們把上面的代碼加一點(diǎn)點(diǎn)料。

package com.rancho945.concurrent;public class SynchronizeDemo { private Object lockObject = new Object(); //臨界資源(共享變量) private static int count = 0; //A:同步方法 public synchronized void method1(){ count++; } //B:同步靜態(tài)方法 public static synchronized void method2(){ count++; } public void method3(){ //C:同步代碼塊 synchronized (lockObject) { count++; } } public void method4(){ //D:同步代碼塊 synchronized (this) { count++; } } //E:沒(méi)有同步 public void method5() { count++; }}

有可能被多個(gè)線程訪問(wèn)到的資源,我們稱之為臨界資源或共享變量。這里的count變量就是屬于共享變量。那么在多線程的環(huán)境下,對(duì)count的操作是不安全的,比如某個(gè)線程執(zhí)行method1的時(shí)候,另外的線程執(zhí)行了method2或者3或者5。要想對(duì)count變量進(jìn)行線程安全的操作,那么所有操作count變量的都需要同一把鎖。 再看一個(gè)換湯不換藥的:

package com.rancho945.concurrent;public class SynchronizeDemo { private Object lockObject = new Object(); private SynchronizeDemo lockDemo = new SynchronizeDemo(); //臨界資源(共享資源) private static int count = 0; //A:同步方法 public synchronized void method1(){ count++; } //B:同步靜態(tài)方法 public static synchronized void method2(){ count++; } public void method3(){ //C:同步代碼塊 synchronized (lockObject) { count++; } } public void method4(){ //D:同步代碼塊 synchronized (this) { count++; } } //E:沒(méi)有同步 public void method5() { count++; } public void method6() { //F lockDemo.method1(); } public void method7() { //G lockDemo.method4(); } public void method8() { //H synchronized (lockDemo) { } } public void method9() { //I lockDemo.method3(); }}

這里的FGH都是同一把鎖,他們之間是互斥的,因?yàn)槭褂玫亩际莑ockDemo對(duì)象的鎖。而I與FGH不互斥,因?yàn)橛玫氖莑ockDemo中的lockObject對(duì)象的鎖

在發(fā)生異常的時(shí)候,JVM會(huì)自動(dòng)釋放鎖,因此不會(huì)因?yàn)楫惓6l(fā)生死鎖

那么我們開始思考,為什么鎖的設(shè)計(jì)會(huì)是放在對(duì)象上而不是放在線程上呢?

答案從我們的生活中找,比如說(shuō),你(線程)上廁所(對(duì)象),是自己每次都帶一把鎖還是廁所門上裝一把鎖?這道理同樣適合用于Java鎖的設(shè)計(jì),同時(shí)也更好地解釋了:

當(dāng)執(zhí)行Thread.sleep()的時(shí)候?yàn)槭裁床粫?huì)釋放鎖(相當(dāng)你在廁所睡著了,廁所還是鎖著的); wait方法是在Object上而不是Thread上(鎖在廁所門上而不是在你手上); 必須獲得對(duì)象鎖才能調(diào)用wait和notify、notifyAll方法(廁所門的鎖控制權(quán)在你手上你才能決定是否把廁所讓給別人用)。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 宁远县| 三亚市| 辽阳县| 威信县| 凤山市| 治多县| 武清区| 丰台区| 营口市| 商城县| 民和| 盐城市| 萍乡市| 曲阜市| 肇州县| 瑞安市| 武邑县| 贡山| 元朗区| 隆尧县| 张家界市| 锡林浩特市| 贡嘎县| 定远县| 炎陵县| 高雄县| 灵寿县| 阿城市| 盱眙县| 武陟县| 达孜县| 特克斯县| 龙游县| 南宫市| 黄梅县| 金湖县| 太湖县| 四会市| 江安县| 蒙自县| 宁城县|