大漠駝鈴

          置身浩瀚的沙漠,方向最為重要,希望此blog能向大漠駝鈴一樣,給我方向和指引。
          Java,Php,Shell,Python,服務(wù)器運(yùn)維,大數(shù)據(jù),SEO, 網(wǎng)站開發(fā)、運(yùn)維,云服務(wù)技術(shù)支持,IM服務(wù)供應(yīng)商, FreeSwitch搭建,技術(shù)支持等. 技術(shù)討論QQ群:428622099
          隨筆 - 238, 文章 - 3, 評論 - 117, 引用 - 0
          數(shù)據(jù)加載中……

          Java線程學(xué)習(xí)(2):關(guān)鍵字synchronized

          有了synchronized關(guān)鍵字,多線程程序的運(yùn)行結(jié)果將變得可以控制。synchronized關(guān)鍵字用于保護(hù)共享數(shù)據(jù)。請大家注意"共享數(shù)據(jù)", 你一定要分清哪些數(shù)據(jù)是共享數(shù)據(jù),JAVA是面向?qū)ο蟮某绦蛟O(shè)計(jì)語言,所以初學(xué)者在編寫多線程程序時(shí),容易分不清哪些數(shù)據(jù)是共享數(shù)據(jù)。請看下面的例子:

          實(shí)例一:
          public class FirstThread implements Runnable{
          public synchronized void run(){
          for(int i=1;i<10;i++){
          System.out.println(
          ""+i);
          }
          }
          public FirstThread(){
          }
          public static void main(String[] args){
          Runnable r1
          =new FirstThread();
          Runnable r2
          =new FirstThread();
          Thread t1
          =new Thread(r1);
          Thread t2
          =new Thread(r2);
          t1.start();
          t2.start();

          }

          }
          在這個(gè)程序中,run()被加上了synchronized關(guān)鍵字。在main方法中創(chuàng)建了兩個(gè)線程。你可能會(huì)認(rèn)為此程序的運(yùn)行結(jié)果一定為:0123456789  0123456789。答案不是這樣子的,這個(gè)程序中synchronized關(guān)鍵字保護(hù)的不是共享數(shù)據(jù)(其實(shí)在這個(gè)程序中synchronized關(guān) 鍵字沒有起到任何作用,此程序的運(yùn)行結(jié)果是不可預(yù)先確定的)。這個(gè)程序中的t1,t2是兩個(gè)對象(r1,r2)的線程。JAVA是面向?qū)ο蟮某绦蛟O(shè)計(jì)語 言,不同的對象的數(shù)據(jù)是不同的,r1,r2有各自的run()方法,而synchronized使同一個(gè)對象的多個(gè)線程,在某個(gè)時(shí)刻只有其中的一個(gè)線程可 以訪問這個(gè)對象的synchronized數(shù)據(jù)。每個(gè)對象都有一個(gè)"鎖標(biāo)志",當(dāng)這個(gè)對象的一個(gè)線程訪問這個(gè)對象的某個(gè)synchronized數(shù)據(jù)時(shí), 這個(gè)對象的所有被synchronized修飾的數(shù)據(jù)將被上鎖(因?yàn)?鎖標(biāo)志"被當(dāng)前線程拿走了),只有當(dāng)前線程訪問完它要訪問的 synchronized數(shù)據(jù)時(shí),當(dāng)前線程才會(huì)釋放"鎖標(biāo)志",這樣同一個(gè)對象的其它線程才有機(jī)會(huì)訪問synchronized數(shù)據(jù)。
          實(shí)例二:
          public class SecondThread implements Runnable{
          public synchronized void run(){
          for(int i=1;i<10;i++){
          System.out.println(
          ""+i);
          }
          }
          public SecondThread(){
          }
          public static void main(String[] args){
          Runnable r
          =new SecondThread();
          //Runnable r2
          =new FirstThread();
          Thread t1
          =new Thread(r);
          Thread t2
          =new Thread(r);
          t1.start();
          t2.start();

          }

          }

          如果你運(yùn)行1000次這個(gè)程序,它的輸出結(jié)果也一定每次都是:01234567890123456789。因?yàn)檫@里的synchronized保護(hù)的是共享數(shù)據(jù)。t1,t2是同一個(gè)對象(r)的兩個(gè)線程,當(dāng)其中的一個(gè)線程(例如:t1)開始執(zhí)行run()方法時(shí),由于run()受 synchronized保護(hù),所以同一個(gè)對象的其他線程(t2)無法訪問synchronized方法(run方法)。只有當(dāng)t1執(zhí)行完后t2才有機(jī)會(huì) 執(zhí)行。

          實(shí)例三:

          public class ThreeThread implements Runnable{
          public  void run(){
          synchronized(this){
          for(int i=1;i<10;i++){
          System.out.println(
          ""+i);
          }}
          }
          public ThreeThread(){
          }
          public static void main(String[] args){
          Runnable r
          =new SecondThree();
          //Runnable r2=new FirstThread();
          Thread t1=new Thread(r);
          Thread t2
          =new Thread(r);
          t1.start();
          t2.start();

          }

          }

          這個(gè)程序與示例2的運(yùn)行結(jié)果一樣。在可能的情況下,應(yīng)該把保護(hù)范圍縮到最小,可以用示例3的形式,this代表"這個(gè)對象"。沒有必要把整個(gè)run()保護(hù)起來,run()中的代碼只有一個(gè)for循環(huán),所以只要保護(hù)for循環(huán)就可以了。

          實(shí)例四:
          public class FourThread implements Runnable{
          public  void run(){
          for(int i=1;i<10;i++){
          System.out.println(
          Thread.currentThread().getName()+"forloop"+i);
          }

          synchronized(this){
          for(int i=1;i<10;i++){
          System.out.println(
          Thread.currentThread().getName()+"synchronized"+i);
          }}
          }
          public SecondThread(){
          }
          public static void main(String[] args){
          Runnable r
          =new ThreeThread();
          //Runnable r2=new FirstThread();
          Thread t1=new Thread(r);
          Thread t2
          =new Thread(r);
          t1.start();
          t2.start();

          }

          }
          t1_name:forloop:0
          t1_name:forloop:1
          t1_name:forloop:2
          t2_name:forloop:0
          t1_name:forloop:3
          t2_name:forloop:1
          t1_name:forloop:4
          t2_name:forloop:2
          t1_name:synchronizedforloop:0
          t2_name:forloop:3
          t1_name:synchronizedforloop:1
          t2_name:forloop:4
          t1_name:synchronizedforloop:2
          t1_name:synchronizedforloop:3
          t1_name:synchronizedforloop:4
          t2_name:synchronizedforloop:0
          t2_name:synchronizedforloop:1
          t2_name:synchronizedforloop:2
          t2_name:synchronizedforloop:3
          t2_name:synchronizedforloop:4
          第一個(gè)for循環(huán)沒有受synchronized保護(hù)。對于第一個(gè)for循環(huán),t1,t2可以同時(shí)訪問。運(yùn)行結(jié)果
          表明t1執(zhí)行到了k=2 時(shí),t2開始執(zhí)行了。t1首先執(zhí)行完了第一個(gè)for循環(huán),此時(shí)還沒有執(zhí)行完第一個(gè)
          for循環(huán)(t2剛執(zhí)行到k=2)。t1開始執(zhí)行第二個(gè)for循環(huán),當(dāng) t1的第二個(gè)for循環(huán)執(zhí)行到k=1時(shí),t2
          的第一個(gè)for循環(huán)執(zhí)行完了。http://bianceng.cn(編程入門)
          t2想開始執(zhí)行第二個(gè)for循環(huán),但由于t1首先執(zhí)行了第二個(gè)for循環(huán),這個(gè)對象的鎖標(biāo)志自然在
          t1手中(synchronized方法的執(zhí)行權(quán)也就落到了t1手中),在t1沒執(zhí)行完第二個(gè)for循環(huán)的時(shí)候,它
          是不會(huì)釋放鎖標(biāo)志的。
          所以t2必須等到t1執(zhí)行完第二個(gè)for循環(huán)后,它才可以執(zhí)行第二個(gè)for循環(huán)

          posted on 2009-02-26 19:43 草原上的駱駝 閱讀(415) 評論(0)  編輯  收藏 所屬分類: JAVA基礎(chǔ)知識

          主站蜘蛛池模板: 禹州市| 大洼县| 阿克陶县| 阳西县| 湖州市| 宾川县| 莱州市| 灌阳县| 宜宾县| 波密县| 富平县| 三穗县| 绿春县| 弥勒县| 雅江县| 天等县| 郸城县| 庐江县| 翁牛特旗| 娱乐| 乌鲁木齐市| 荥经县| 沂南县| 阿鲁科尔沁旗| 双城市| 山阴县| 通渭县| 罗田县| 逊克县| 桂林市| 武乡县| 涟源市| 宜兰市| 丹阳市| 锦屏县| 搜索| 视频| 淄博市| 即墨市| 常宁市| 潍坊市|