一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 詳解java中的synchronized關鍵字

詳解java中的synchronized關鍵字

2020-03-06 20:02Gang.Wang JAVA教程

這篇文章主要介紹了java中的synchronized關鍵字,可用來給對象和方法或者代碼塊加鎖,當它鎖定一個方法或者一個代碼塊的時候,同一時刻最多只有一個線程執行這段代碼,感興趣的小伙伴們可以參考一下

Java語言的關鍵字,當它用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻最多只有一個線程執行該段代碼。

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

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

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package ths;
 
public class Thread1 implements Runnable {
   public void run() {
     synchronized(this) {
        for (int i = 0; i < 5; i++) {
          System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
        }
     }
   }
   public static void main(String[] args) {
     Thread1 t1 = new Thread1();
     Thread ta = new Thread(t1, "A");
     Thread tb = new Thread(t1, "B");
     ta.start();
     tb.start();
   }
}

結果:  
     A synchronized loop 0 
     A synchronized loop 1 
     A synchronized loop 2 
     A synchronized loop 3 
     A synchronized loop 4 
     B synchronized loop 0 
     B synchronized loop 1 
     B synchronized loop 2 
     B synchronized loop 3 
     B synchronized loop 4

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

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package ths;
 
public class Thread2 {
   public void m4t1() {
     synchronized(this) {
        int i = 5;
        while( i-- > 0) {
          System.out.println(Thread.currentThread().getName() + " : " + i);
          try {
             Thread.sleep(500);
          } catch (InterruptedException ie) {
          }
        }
     }
   }
   public void m4t2() {
     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 Thread2 myt2 = new Thread2();
     Thread t1 = new Thread( new Runnable() { public void run() { myt2.m4t1(); } }, "t1" );
     Thread t2 = new Thread( new Runnable() { public void run() { myt2.m4t2();  } }, "t2" );
     t1.start();
     t2.start();
   }
}

結果:  
     t1 : 4 
     t2 : 4 
     t1 : 3 
     t2 : 3 
     t1 : 2 
     t2 : 2 
     t1 : 1 
     t2 : 1 
     t1 : 0 
     t2 : 0

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

修改Thread2.m4t2()方法:     

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public void m4t2() {
    synchronized(this) {
       int i = 5;
       while( i-- > 0) {
         System.out.println(Thread.currentThread().getName() + " : " + i);
         try {
            Thread.sleep(500);
         } catch (InterruptedException ie) {
         }
       }
    }
 
  }

結果:

     t1 : 4 
     t1 : 3 
     t1 : 2 
     t1 : 1 
     t1 : 0 
     t2 : 4 
     t2 : 3 
     t2 : 2 
     t2 : 1 
     t2 : 0

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

修改Thread2.m4t2()方法如下:    

?
1
2
3
4
5
6
7
8
9
10
public synchronized void m4t2() {
     int i = 5;
     while( i-- > 0) {
        System.out.println(Thread.currentThread().getName() + " : " + i);
        try {
          Thread.sleep(500);
        } catch (InterruptedException ie) {
        }
     }
   }

結果:  
     t1 : 4 
     t1 : 3 
     t1 : 2 
     t1 : 1 
     t1 : 0 
     t2 : 4 
     t2 : 3 
     t2 : 2 
     t2 : 1 
     t2 : 0

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

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package ths;
 
public class Thread3 {
   class Inner {
     private void m4t1() {
        int i = 5;
        while(i-- > 0) {
          System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);
          try {
             Thread.sleep(500);
          } catch(InterruptedException ie) {
          }
        }
     }
     private void m4t2() {
        int i = 5;
        while(i-- > 0) {
          System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
          try {
             Thread.sleep(500);
          } catch(InterruptedException ie) {
          }
        }
     }
   }
   private void m4t1(Inner inner) {
     synchronized(inner) { //使用對象鎖
     inner.m4t1();
   }
   private void m4t2(Inner inner) {
     inner.m4t2();
   }
   public static void main(String[] args) {
     final Thread3 myt3 = new Thread3();
     final Inner inner = myt3.new Inner();
     Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");
   Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");
   t1.start();
   t2.start();
 }
}

結果:

盡管線程t1獲得了對Inner的對象鎖,但由于線程t2訪問的是同一個Inner中的非同步部分。所以兩個線程互不干擾。

     t1 : Inner.m4t1()=4 
     t2 : Inner.m4t2()=4 
     t1 : Inner.m4t1()=3 
     t2 : Inner.m4t2()=3 
     t1 : Inner.m4t1()=2 
     t2 : Inner.m4t2()=2 
     t1 : Inner.m4t1()=1 
     t2 : Inner.m4t2()=1 
     t1 : Inner.m4t1()=0 
     t2 : Inner.m4t2()=0

現在在Inner.m4t2()前面加上synchronized:

?
1
2
3
4
5
6
7
8
9
10
private synchronized void m4t2() {
    int i = 5;
    while(i-- > 0) {
       System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);
       try {
         Thread.sleep(500);
       } catch(InterruptedException ie) {
       }
    }
  }

結果:

盡管線程t1與t2訪問了同一個Inner對象中兩個毫不相關的部分,但因為t1先獲得了對Inner的對象鎖,所以t2對Inner.m4t2()的訪問也被阻塞,因為m4t2()是Inner中的一個同步方法。

     t1 : Inner.m4t1()=4 
     t1 : Inner.m4t1()=3 
     t1 : Inner.m4t1()=2 
     t1 : Inner.m4t1()=1 
     t1 : Inner.m4t1()=0 
     t2 : Inner.m4t2()=4 
     t2 : Inner.m4t2()=3 
     t2 : Inner.m4t2()=2 
     t2 : Inner.m4t2()=1 
     t2 : Inner.m4t2()=0
synchronized 關鍵字,它包括兩種用法:synchronized 方法synchronized 塊。 
1. synchronized 方法:通過在方法聲明中加入 synchronized關鍵字來聲明 synchronized 方法。如: 
public synchronized void accessVal(int newVal); 
synchronized 方法控制對類成員變量的訪問:每個類實例對應一把鎖,每個 synchronized 方法都必須獲得調用該方法的類實例的鎖方能執行,否則所屬線程阻塞,方法一旦執行,就獨占該鎖,直到從該方法返回時才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進入可執行狀態。這種機制確保了同一時刻對于每一個類實例,其所有聲明為 synchronized 的成員函數中至多只有一個處于可執行狀態(因為至多只有一個能夠獲得該類實例對應的鎖),從而有效避免了類成員變量的訪問沖突(只要所有可能訪問類成員變量的方法均被聲明為 synchronized)。 
在 Java 中,不光是類實例,每一個類也對應一把鎖,這樣我們也可將類的靜態成員函數聲明為 synchronized ,以控制其對類的靜態成員變量的訪問。 
synchronized 方法的缺陷:若將一個大的方法聲明為synchronized 將會大大影響效率,典型地,若將線程類的方法 run() 聲明為synchronized ,由于在線程的整個生命期內它一直在運行,因此將導致它對本類任何 synchronized 方法的調用都永遠不會成功。當然我們可以通過將訪問類成員變量的代碼放到專門的方法中,將其聲明為 synchronized ,并在主方法中調用來解決這一問題,但是 Java 為我們提供了更好的解決辦法,那就是 synchronized 塊。 
2. synchronized 塊:通過 synchronized關鍵字來聲明synchronized 塊。語法如下: 
synchronized(syncObject) { 
//允許訪問控制的代碼 

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

以上就是關于java synchronized關鍵字的詳細實例介紹,希望能夠幫助大家更好的學習synchronized關鍵字的用法。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 插鸡网站| 欧美日韩在线观看一区二区 | 日本护士厕所xxx | 国外欧美一区另类中文字幕 | 四虎现在的网址入口2022 | 日本一区二区三区四区无限 | 精品一区二区三区色花堂 | 欧美vpswindowssex| av91在线 | 久久久久久久电影 | 国产成人影院在线观看 | 国产精品免费看香蕉 | 日韩天堂在线 | 国产精品免费观在线 | 男人j进女屁股视频在线观看 | 日本激情小说 | 亚洲码在线观看 | 久久99精品久久久久久园产越南 | h片免费网站 | 欧美vpswindows动物 | 色综合亚洲精品激情狠狠 | coolgay男男gayxxx chinese壮直男gay老年人 chinese野外gay军人 | 99热国产在线 | 日产精品一二三四区国产 | 91精品国产免费久久国语蜜臀 | 色亚| 亚洲欧美国产另类视频 | 欧美5g影院| 高清男的插曲女的 欢迎你老狼 | 亚洲国产精品第一区二区三区 | 国产视频久久久久 | 亚洲老头与老太hd | 午夜伦伦电影理论片费看 | 亚洲精品国产乱码AV在线观看 | 欧美日韩一二三区免费视频观看 | 亚洲一区二区三区福利在线 | futa百合文| 日本视频免费看 | 麻豆网站视频国产在线观看 | 乌克兰一级毛片9一18 | 色综合久久丁香婷婷 |