亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

透徹理解Java中Synchronized(對象鎖)和Static Synchronized(類鎖)的區別

2024-07-14 08:40:49
字體:
來源:轉載
供稿:網友

本文講述了Java中Synchronized(對象鎖)和Static Synchronized(類鎖)的區別。分享給大家供大家參考,具體如下:

Synchronized和Static Synchronized區別

通過分析這兩個用法的分析,我們可以理解java中鎖的概念。一個是實例鎖(鎖在某一個實例對象上,如果該類是單例,那么該鎖也具有全局鎖的概念),一個是全局鎖(該鎖針對的是類,無論實例多少個對象,那么線程都共享該鎖)。實例鎖對應的就是synchronized關鍵字,而類鎖(全局鎖)對應的就是static synchronized(或者是鎖在該類的class或者classloader對象上)。

下面的文章做了很好的總結:

1.synchronized與static synchronized 的區別

synchronized是對類的當前實例(當前對象)進行加鎖,防止其他線程同時訪問該類的該實例的所有synchronized塊,注意這里是“類的當前實例”, 類的兩個不同實例就沒有這種約束了。

那么static synchronized恰好就是要控制類的所有實例的并發訪問,static synchronized是限制多線程中該類的所有實例同時訪問jvm中該類所對應的代碼塊。實際上,在類中如果某方法或某代碼塊中有 synchronized,那么在生成一個該類實例后,該實例也就有一個監視塊,防止線程并發訪問該實例的synchronized保護塊,而static synchronized則是所有該類的所有實例公用得一個監視塊,這就是他們兩個的區別。也就是說synchronized相當于 this.synchronized,而static synchronized相當于Something.synchronized.(后面又講解)

一個日本作者-結成浩的《java多線程設計模式》有這樣的一個列子:

pulbic class Something(){  public synchronized void isSyncA(){}  public synchronized void isSyncB(){}  public static synchronized void cSyncA(){}  public static synchronized void cSyncB(){} } 

那么,假如有Something類的兩個實例x與y,那么下列各組方法被多線程同時訪問的情況是怎樣的?

a. x.isSyncA()與x.isSyncB()
b. x.isSyncA()與y.isSyncA()
c. x.cSyncA()與y.cSyncB()
d. x.isSyncA()與Something.cSyncA()

這里,很清楚的可以判斷:

a,都是對同一個實例(x)的synchronized域訪問,因此不能被同時訪問。(多線程中訪問x的不同synchronized域不能同時訪問)

如果在多個線程中訪問x.isSyncA(),因為仍然是對同一個實例,且對同一個方法加鎖,所以多個線程中也不能同時訪問。(多線程中訪問x的同一個synchronized域不能同時訪問)

b,是針對不同實例的,因此可以同時被訪問(對象鎖對于不同的對象實例沒有鎖的約束)

c,因為是static synchronized,所以不同實例之間仍然會被限制,相當于Something.isSyncA()與 Something.isSyncB()了,因此不能被同時訪問。

那么,第d呢?,書上的 答案是可以被同時訪問的,答案理由是synchronzied的是實例方法與synchronzied的類方法由于鎖定(lock)不同的原因。

個人分析也就是synchronized 與static synchronized 相當于兩幫派,各自管各自,相互之間就無約束了,可以被同時訪問。

舉個例子:

public class TestSynchronized {  public synchronized void test1()  {  int i = 5;  while( i-- > 0)  {  System.out.println(Thread.currentThread().getName() + " : " + i);  try  {  Thread.sleep(500);  }  catch (InterruptedException ie)  {  }  }  }  public static synchronized void test2()  {  int i = 5;  while( i-- > 0)  {  System.out.println(Thread.currentThread().getName() + " : " + i);  try  {  Thread.sleep(500);  }  catch (InterruptedException ie)  {  }  }  }  public static void main(String[] args)  {  final TestSynchronized myt2 = new TestSynchronized();  Thread test1 = new Thread( new Runnable() { public void run() { myt2.test1(); } }, "test1" );  Thread test2 = new Thread( new Runnable() { public void run() { TestSynchronized.test2(); } }, "test2" );  test1.start();  test2.start(); // TestRunnable tr=new TestRunnable(); // Thread test3=new Thread(tr); // test3.start();  } } 
test1 : 4 test2 : 4 test1 : 3 test2 : 3 test2 : 2 test1 : 2 test2 : 1 test1 : 1 test1 : 0 test2 : 0 

上面代碼synchronized同時修飾靜態方法和實例方法,但是運行結果是交替進行的,這證明了類鎖和對象鎖是兩個不一樣的鎖,控制著不同的區域,它們是互不干擾的。同樣,線程獲得對象鎖的同時,也可以獲得該類鎖,即同時獲得兩個鎖,這是允許的。

結論:

A: synchronized static是某個類的范圍,synchronized static cSync{}防止多個線程中多個實例同時訪問這個 類中的synchronized static 方法。它可以對類的所有對象實例起作用。

B: synchronized 是某實例的范圍,synchronized isSync(){}防止多個線程中這一個實例同時訪問這個類的synchronized 方法。

其實總結起來很簡單。

  • 一個鎖的是類對象,一個鎖的是實例對象。
  • 若類對象被lock,則類對象的所有同步方法全被lock;
  • 若實例對象被lock,則該實例對象的所有同步方法全被lock。

2.synchronized方法與synchronized代碼快的區別

synchronized methods(){} 與synchronized(this){}之間沒有什么區別,只是synchronized methods(){} 便于閱讀理解,而synchronized(this){}可以更精確的控制沖突限制訪問區域,有時候表現更高效率。

兩種方式效率比較:

1、同步塊,代碼如下:

import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestSynchronized {  /**  * @param args  */  public static void main(String[] args) {  ExecutorService service = Executors.newCachedThreadPool();  final CountDownLatch cdOrder = new CountDownLatch(1);  final CountDownLatch cdAnswer = new CountDownLatch(3);  final SynchonizedClass sc = new SynchonizedClass();  for(int i=0; i<3; i++){  Runnable runnable = new Runnable(){  public void run() {  try{  cdOrder.await();  sc.start();  cdAnswer.countDown();  }catch(Exception e){  e.printStackTrace();  }  }  };  service.execute(runnable);  }  try{  Thread.sleep((long) (Math.random()*10000));  System.out.println("線程" + Thread.currentThread().getName() +  "發布執行命令");  cdOrder.countDown();  long beginTime = System.currentTimeMillis();  System.out.println("線程" + Thread.currentThread().getName() +  "已經發送命令,正在等待結果");  cdAnswer.await();  System.out.println("線程" + Thread.currentThread().getName() +  "已收到所有響應結果,所用時間為:" + (System.currentTimeMillis()-beginTime));  }catch(Exception e){  e.printStackTrace();  }  service.shutdown();  } } class SynchonizedClass{  public void start() throws InterruptedException{  Thread.sleep(100);//執行其它邏輯消耗時間  synchronized(this){  System.out.println("我運行使用了 10 ms");  }  } } 

運行結果如下:

線程main發布執行命令
線程main已經發送命令,正在等待結果
我運行使用了 10 ms
我運行使用了 10 ms
我運行使用了 10 ms
線程main已收到所有響應結果,所用時間為:110

同步方法,代碼如下:

import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestSynchronized {  /**  * @param args  */  public static void main(String[] args) {  ExecutorService service = Executors.newCachedThreadPool();  final CountDownLatch cdOrder = new CountDownLatch(1);  final CountDownLatch cdAnswer = new CountDownLatch(3);  final SynchonizedClass sc = new SynchonizedClass();  for(int i=0; i<3; i++){  Runnable runnable = new Runnable(){  public void run() {  try{  cdOrder.await();  sc.start();  cdAnswer.countDown();  }catch(Exception e){  e.printStackTrace();  }  }  };  service.execute(runnable);  }  try{  Thread.sleep((long) (Math.random()*10000));  System.out.println("線程" + Thread.currentThread().getName() +  "發布執行命令");  cdOrder.countDown();  long beginTime = System.currentTimeMillis();  System.out.println("線程" + Thread.currentThread().getName() +  "已經發送命令,正在等待結果");  cdAnswer.await();  System.out.println("線程" + Thread.currentThread().getName() +  "已收到所有響應結果,所用時間為:" + (System.currentTimeMillis()-beginTime));  }catch(Exception e){  e.printStackTrace();  }  service.shutdown();  } } class SynchonizedClass{  public synchronized void start() throws InterruptedException{  Thread.sleep(100);//執行其它邏輯消耗時間 // synchronized(this){  System.out.println("我運行使用了 10 ms"); // }  } } 

運行結果如下:

線程main發布執行命令
線程main已經發送命令,正在等待結果
我運行使用了 10 ms
我運行使用了 10 ms
我運行使用了 10 ms
線程main已收到所有響應結果,所用時間為:332

兩者相差:222ms。

 對比說明同步代碼塊比同步方法效率更高。

補充記憶:

1、synchronized關鍵字的作用域有二種:

1)是某個對象實例內,synchronized aMethod(){}可以防止多個線程同時訪問這個對象的synchronized方法(如果一個對象有多個synchronized方法,只要一個線程訪問了其中的一個synchronized方法,其它線程不能同時訪問這個對象中任何一個synchronized方法)。這時,不同的對象實例的synchronized方法是不相干擾的。也就是說,其它線程照樣可以同時訪問相同類的另一個對象實例中的synchronized方法;

2)是某個類的范圍,synchronized static aStaticMethod{}防止多個線程中不同的實例對象(或者同一個實例對象)同時訪問這個類中的synchronized static 方法。它可以對類的所有對象實例起作用。

2、除了方法前用synchronized關鍵字,synchronized關鍵字還可以用于方法中的某個區塊中,表示只對這個區塊的資源實行互斥訪問。用法是: synchronized(this){/*區塊*/}(或者synchronized(obj){/*區塊*/}),它的作用域是當前對象;

3、synchronized關鍵字是不能繼承的,也就是說,基類的方法synchronized f(){} 在繼承類中并不自動是synchronized f(){},而是變成了f(){}。繼承類需要你顯式的指定它的某個方法為synchronized方法; 

對synchronized(this)的一些理解(很好的解釋了對象鎖,注意其中的this關鍵字)  

一、當兩個并發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以后才能執行該代碼塊?!?/p>

二、然而,當一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊?! ?/p>

三、尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞?! ?/p>

四、第三個例子同樣適用其它同步代碼塊。也就是說,當一個線程訪問object的一個synchronized(this)同步代碼塊時,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪問都被暫時阻塞?! ?/p>

五、以上規則對其它對象鎖同樣適用

補充一段代碼,方便對synchronized關鍵字進行測試(簡單修改即可)

public class TestSynchronized {  public void test1()  {  synchronized(this)  {  int i = 5;  while( i-- > 0)  {  System.out.println(Thread.currentThread().getName() + " : " + i);  try  {  Thread.sleep(500);  }  catch (InterruptedException ie)  {  }  }  }  }  public synchronized void test2()  {  int i = 5;  while( i-- > 0)  {  System.out.println(Thread.currentThread().getName() + " : " + i);  try  {  Thread.sleep(500);  }  catch (InterruptedException ie)  {  }  }  }  public synchronized void test3()  {  int i = 5;  while( i-- > 0)  {  System.out.println(Thread.currentThread().getName() + " : " + i);  try  {  Thread.sleep(500);  }  catch (InterruptedException ie)  {  }  }  }  public static void main(String[] args)  {  final TestSynchronized myt2 = new TestSynchronized();  final TestSynchronized myt3 = new TestSynchronized();  Thread test1 = new Thread( new Runnable() { public void run() { myt2.test2(); } }, "test1" );  Thread test2 = new Thread( new Runnable() { public void run() { myt2.test3(); } }, "test3" );  test1.start();;  test2.start();  } } 

運行結果:

test1 : 4test1 : 3test1 : 2test1 : 1test1 : 0test3 : 4test3 : 3test3 : 2test3 : 1test3 : 0

下面我們著重介紹java中的 Sychronized的用法,具體為:同步方法 與 同步塊synchronized 關鍵字,它包括兩種用法:synchronized 方法和 synchronized 塊。 

1. synchronized 方法:通過在方法聲明中加入 synchronized關鍵字來聲明 synchronized 方法。如: 

public synchronized void accessVal(int newVal);

synchronized 方法控制對類成員變量的訪問:每個類實例對應一把鎖,每個 synchronized 方法都必須獲得調用該方法的類實例的鎖方能執行,否則所屬線程阻塞,方法一旦執行,就獨占該鎖,直到從該方法返回時才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進入可執行狀態。這種機制確保了同一時刻對于每一個類實例,其所有聲明為 synchronized 的成員函數中至多只有一個處于可執行狀態(因為至多只有一個能夠獲得該類實例對應的鎖),從而有效避免了類成員變量的訪問沖突(只要所有可能訪問類成員變量的方法均被聲明為 synchronized)。

在 Java 中,不光是類實例,每一個類也對應一把鎖,這樣我們也可將類的靜態成員函數聲明為static  synchronized ,以控制其對類的靜態成員變量的訪問。

synchronized 方法的缺陷:若將一個大的方法聲明為synchronized 將會大大影響效率,典型地,若將線程類的方法 run() 聲明為 synchronized ,由于在線程的整個生命期內它一直在運行,因此將導致它對本類任何 synchronized 方法的調用都永遠不會成功。當然我們可以通過將訪問類成員變量的代碼放到專門的方法中,將其聲明為 synchronized ,并在主方法中調用來解決這一問題,但是 Java 為我們提供了更好的解決辦法,那就是 synchronized 塊。  

2. synchronized 塊:通過 synchronized關鍵字來聲明synchronized 塊。語法如下:  

synchronized(syncObject) {  //允許訪問控制的代碼  }

synchronized 塊是這樣一個代碼塊,其中的代碼必須獲得對象 syncObject (如前所述,可以是類實例或類)的鎖方能執行,具體機制同前所述。由于可以針對任意代碼塊,且可任意指定上鎖的對象,故靈活性較高。

注意:

在使用synchronized關鍵字時候,應該盡可能避免在synchronized方法或synchronized塊中使用sleep或者yield方法,因為synchronized程序塊占有著對象鎖,你休息那么其他的線程只能一邊等著你醒來執行完了才能執行。不但嚴重影響效率,也不合邏輯。

同樣,在同步程序塊內調用yeild方法讓出CPU資源也沒有意義,因為你占用著鎖,其他互斥線程還是無法訪問同步程序塊。當然與同步程序塊無關的線程可以獲得更多的執行時間。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久最新网址| 国产日本欧美视频| 久久久亚洲影院你懂的| 日韩性xxxx爱| 欧美日韩国产区| 日日噜噜噜夜夜爽亚洲精品| 欧美夜福利tv在线| 国产脚交av在线一区二区| 夜夜嗨av色一区二区不卡| 国产福利成人在线| 亚洲精品小视频在线观看| 夜夜嗨av一区二区三区四区| 色噜噜久久综合伊人一本| 91wwwcom在线观看| www.国产精品一二区| 国产精品男女猛烈高潮激情| 午夜精品久久久久久久99黑人| 日韩视频精品在线| 久久夜色精品国产| 国色天香2019中文字幕在线观看| 国产精品精品国产| 亚洲视频在线视频| 欧美精品久久久久久久久久| 亚洲成人av资源网| 正在播放欧美一区| 91亚洲国产精品| 欧美日韩在线一区| 成人精品一区二区三区电影免费| 亚洲激情在线视频| 97精品视频在线| 精品一区二区电影| 91美女片黄在线观| 亚洲欧洲在线免费| 日韩精品免费在线观看| 国模精品系列视频| 欧美在线亚洲一区| 国产精品日韩久久久久| 亚洲综合在线中文字幕| 国产成人免费91av在线| 中文字幕亚洲精品| 欧美综合一区第一页| 成人有码视频在线播放| 国产精品视频在线播放| 夜夜嗨av色一区二区不卡| 成人免费网站在线| 色偷偷噜噜噜亚洲男人| 国产精品一区二区久久精品| 精品中文字幕久久久久久| 亚洲国产精品久久久久秋霞蜜臀| 欧美性xxxx极品hd欧美风情| 亚洲国产美女精品久久久久∴| 日本一区二区三区四区视频| 亚洲qvod图片区电影| 亚洲精品国产成人| 亚洲一区二区三区久久| 在线电影欧美日韩一区二区私密| 日韩电影免费在线观看中文字幕| 成人免费淫片视频软件| 日韩av在线免费| 国产精品久久久久久久久久东京| 96sao精品视频在线观看| 亚洲欧洲视频在线| 富二代精品短视频| 欧美夫妻性视频| 91亚洲精华国产精华| 黑人极品videos精品欧美裸| 国产精品美女在线| 91久久久在线| 欧美电影在线观看| 中文字幕一精品亚洲无线一区| 亚洲图片在线综合| 91人人爽人人爽人人精88v| 久久久久久这里只有精品| 欧美一级淫片丝袜脚交| 亚洲精品一区在线观看香蕉| 日韩在线观看你懂的| 欧美丰满少妇xxxxx| 日韩精品在线观看一区| 精品视频中文字幕| 国产精品福利观看| 亚洲电影免费观看高清完整版| 亚洲永久在线观看| 亚洲天堂av在线播放| 一区二区欧美在线| 日韩精品电影网| 精品亚洲一区二区三区| 亚洲国模精品私拍| 久久免费少妇高潮久久精品99| 国产精品在线看| 午夜精品一区二区三区在线视| 欧美裸身视频免费观看| 最近中文字幕2019免费| 欧美特级www| 亚洲福利精品在线| 成人写真福利网| 成人性生交大片免费看视频直播| 中文字幕综合在线| 亚洲韩国日本中文字幕| 中国人与牲禽动交精品| 精品国产老师黑色丝袜高跟鞋| 亚洲欧美一区二区三区四区| 国产亚洲精品一区二区| 久久99久久99精品中文字幕| 亚洲第一福利视频| 日韩在线观看免费全| 91经典在线视频| 国产日韩在线亚洲字幕中文| 久久久精品中文字幕| 久久免费精品日本久久中文字幕| 高清亚洲成在人网站天堂| 美女黄色丝袜一区| 91精品在线国产| 国产97在线播放| 欧美精品videossex性护士| 国产a级全部精品| 亚洲精品白浆高清久久久久久| 久久99精品久久久久久噜噜| 精品成人乱色一区二区| 国产精品久久久久久久久久小说| 欧美第一黄网免费网站| 国产69精品99久久久久久宅男| 亚洲视频一区二区三区| 国产精品欧美一区二区三区奶水| 91精品国产高清自在线| 亚洲美女精品久久| 久久久av网站| 亚洲欧美日韩在线一区| 91国产美女在线观看| 亚洲精品网站在线播放gif| 欧美日韩国产123| 91高清视频免费| 亚洲伦理中文字幕| 日韩在线观看免费| 日韩av电影免费观看高清| 日韩美女在线观看| 亚洲香蕉伊综合在人在线视看| 精品夜色国产国偷在线| 国产精品视频xxx| 成人xvideos免费视频| 国产精品美女www爽爽爽视频| 亚洲成人av中文字幕| www高清在线视频日韩欧美| 欧美精品少妇videofree| 国产精品美乳一区二区免费| 日韩亚洲欧美中文高清在线| 91亚洲精华国产精华| 欧美美女操人视频| 国产亚洲精品一区二区| 日韩电影免费观看在线| 午夜精品一区二区三区在线| 亚洲视频国产视频| 欧美亚洲激情视频| 国产午夜精品免费一区二区三区| 国产亚洲一区二区在线| 欧美成人免费大片| 亚洲精品美女久久久久| 国产精品福利网| 国产精品美女主播在线观看纯欲| 亚洲人高潮女人毛茸茸| 91免费国产视频| 久久综合免费视频影院| 亚洲爱爱爱爱爱| 久久久久久亚洲精品| 久久久国产精品免费|