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

首頁 > 編程 > Java > 正文

詳解java中的synchronized關(guān)鍵字

2019-11-26 14:47:57
字體:
供稿:網(wǎng)友

Java語言的關(guān)鍵字,當(dāng)它用來修飾一個(gè)方法或者一個(gè)代碼塊的時(shí)候,能夠保證在同一時(shí)刻最多只有一個(gè)線程執(zhí)行該段代碼。

一、當(dāng)兩個(gè)并發(fā)線程訪問同一個(gè)對(duì)象object中的這個(gè)synchronized(this)同步代碼塊時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊。

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

三、尤其關(guān)鍵的是,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),其他線程對(duì)object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

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

 五、以上規(guī)則對(duì)其它對(duì)象鎖同樣適用。

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

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();    } }

結(jié)果:  
     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

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

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();    } }

結(jié)果:  
     t1 : 4 
     t2 : 4 
     t1 : 3 
     t2 : 3 
     t1 : 2 
     t2 : 2 
     t1 : 1 
     t2 : 1 
     t1 : 0 
     t2 : 0

三、尤其關(guān)鍵的是,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),其他線程對(duì)object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

修改Thread2.m4t2()方法:     

 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) {           }         }      }   }

結(jié)果:

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

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

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

public synchronized void m4t2() {      int i = 5;      while( i-- > 0) {         System.out.println(Thread.currentThread().getName() + " : " + i);         try {           Thread.sleep(500);         } catch (InterruptedException ie) {         }      }    }

結(jié)果:  
     t1 : 4 
     t1 : 3 
     t1 : 2 
     t1 : 1 
     t1 : 0 
     t2 : 4 
     t2 : 3 
     t2 : 2 
     t2 : 1 
     t2 : 0

五、以上規(guī)則對(duì)其它對(duì)象鎖同樣適用:

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) { //使用對(duì)象鎖      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();  } }

結(jié)果:

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

     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

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

 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) {         }      }    }

結(jié)果:

盡管線程t1與t2訪問了同一個(gè)Inner對(duì)象中兩個(gè)毫不相關(guān)的部分,但因?yàn)閠1先獲得了對(duì)Inner的對(duì)象鎖,所以t2對(duì)Inner.m4t2()的訪問也被阻塞,因?yàn)閙4t2()是Inner中的一個(gè)同步方法。

     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 關(guān)鍵字,它包括兩種用法:synchronized 方法synchronized 塊。 
1. synchronized 方法:通過在方法聲明中加入 synchronized關(guān)鍵字來聲明 synchronized 方法。如: 
public synchronized void accessVal(int newVal); 
synchronized 方法控制對(duì)類成員變量的訪問:每個(gè)類實(shí)例對(duì)應(yīng)一把鎖,每個(gè) synchronized 方法都必須獲得調(diào)用該方法的類實(shí)例的鎖方能執(zhí)行,否則所屬線程阻塞,方法一旦執(zhí)行,就獨(dú)占該鎖,直到從該方法返回時(shí)才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進(jìn)入可執(zhí)行狀態(tài)。這種機(jī)制確保了同一時(shí)刻對(duì)于每一個(gè)類實(shí)例,其所有聲明為 synchronized 的成員函數(shù)中至多只有一個(gè)處于可執(zhí)行狀態(tài)(因?yàn)橹炼嘀挥幸粋€(gè)能夠獲得該類實(shí)例對(duì)應(yīng)的鎖),從而有效避免了類成員變量的訪問沖突(只要所有可能訪問類成員變量的方法均被聲明為 synchronized)。 
在 Java 中,不光是類實(shí)例,每一個(gè)類也對(duì)應(yīng)一把鎖,這樣我們也可將類的靜態(tài)成員函數(shù)聲明為 synchronized ,以控制其對(duì)類的靜態(tài)成員變量的訪問。 
synchronized 方法的缺陷:若將一個(gè)大的方法聲明為synchronized 將會(huì)大大影響效率,典型地,若將線程類的方法 run() 聲明為synchronized ,由于在線程的整個(gè)生命期內(nèi)它一直在運(yùn)行,因此將導(dǎo)致它對(duì)本類任何 synchronized 方法的調(diào)用都永遠(yuǎn)不會(huì)成功。當(dāng)然我們可以通過將訪問類成員變量的代碼放到專門的方法中,將其聲明為 synchronized ,并在主方法中調(diào)用來解決這一問題,但是 Java 為我們提供了更好的解決辦法,那就是 synchronized 塊。 
2. synchronized 塊:通過 synchronized關(guān)鍵字來聲明synchronized 塊。語法如下: 
synchronized(syncObject) { 
//允許訪問控制的代碼 

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

以上就是關(guān)于java synchronized關(guān)鍵字的詳細(xì)實(shí)例介紹,希望能夠幫助大家更好的學(xué)習(xí)synchronized關(guān)鍵字的用法。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 内江市| 青川县| 安龙县| 宿松县| 衡山县| 连平县| 罗甸县| 内江市| 甘南县| 固阳县| 北碚区| 游戏| 卫辉市| 探索| 云霄县| 萨嘎县| 邹城市| 房产| 浦东新区| 临桂县| 镇坪县| 新疆| 吴忠市| 鞍山市| 台南县| 巴彦淖尔市| 迁西县| 巩留县| 英德市| 阿拉善右旗| 穆棱市| 武川县| 霍山县| 崇信县| 合肥市| 共和县| 道真| 合阳县| 旬阳县| 平凉市| 常宁市|