<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    OMG,到底在尋找什么..................
    (構造一個完美的J2EE系統所需要的完整知識體系)
    posts - 198,  comments - 37,  trackbacks - 0
    原貼地址:http://www.gbunix.com/htmldata/2004_12/14/19/article_767_1.html

    我突然發現還有很多東西需要我弄明白,比如synchronized這個關鍵字的用法.因為在我昨天進行創建連接池套接字的研究的時候,發現假如我不弄清楚這個概念,根本就無法進行下去,所以我決定將自己對Socket的興趣先冷卻一下,而回過頭來看synchronized.

    看了一上午的Think in Java,覺得還是卓有成效的,應該立即寫下來加深印象.我感覺自己的大腦可重用性極低,總是需要生成新的記憶對象,從而耗費許多重復勞動.所以象記錄,分析,總結這樣類似的工作應該多多益善.

    要弄清synchronized的用法,首先要知道它是用來解決什么問題的.既然synchronized是同步的意思,那么它當然就是來解決不同步的問題的.下面就舉一個不同步的例子來演示可能出現的問題.

    在這個例子當中,我們會創建兩個線程類.一個叫TwoCounter,其工作是對兩個計數器變量同時進行累加,從1開始,你馬上會想道,我們是要用它來實現一個同步.另一個對象叫Watcher,顧名思義,是用來做監視工作的,它負責檢查TwoCounter線程中的兩個計數器的值是否相等,看起來這似乎是毫無意義的工作,因為既然是同步累加的,那么兩個計數器的值怎么可能不相等呢??

    但,事實情況不是這樣的.我們先來看程序.在看這個程序之前,最好先翻翻Think in Java的14.2.1,我的程序實際上是根據該節中給出的例子簡化的,其中的主類改作了Sharing2

    class TwoCounter extends Thread {
    ? private int count1 = 0, count2 = 0;
    ? private boolean started=false;
    ? public void start(){
    ??? if (!started) file://防止多次對一個線程調用Start方法
    ??? {
    ????? started=true;
    ????? super.start();
    ??? }
    ? }
    ? public void run() {
    ??? while (true) {
    ????? count1++;

    file://如果TwoCounter運行到這個時候,CPU時間片被分配給了Watcher,那么這個時候Watcher讀出來的兩個計數器的值當然會不一樣了,這個可能性是存在的。“這是由線程的本質造成的——它們可在任何時候掛起(暫停)。所以在上述兩行的執行時刻之間,有時會出現執行暫停現象。同時,Watcher線程也正好跟隨著進來,并正好在這個時候進行比較,造成計數器出現不相等的情況.”(Think in Java)

    ????? count2++;
    ????? System.out.println("Count1="+count1+",Count2="+count2);
    ????? try {
    ??????? sleep(500);
    ????? } catch (InterruptedException e){}
    ?? }
    ? }

    ? public void synchTest() {
    ??? Sharing2.incrementAccess();
    ??? if(count1 != count2)
    ??????????? System.out.println("Unsynched");//一旦發現不同步,立即顯示
    ? }
    }

    class Watcher extends Thread {
    ? private Sharing2 p;
    ? public Watcher(Sharing2 p) {
    ??? this.p = p;
    ??? start();
    ? }
    ? public void run() {
    ??? while(true) {
    ????? p.s.synchTest();
    ????? try {
    ??????? sleep(500);
    ????? } catch (InterruptedException e){}
    ??? }
    ? }
    }

    public class Sharing2 {
    ? TwoCounter s;
    ? private static int accessCount = 0;
    ? public static void incrementAccess() {
    ??? accessCount++;
    ??? System.out.println("accessCount="+accessCount);
    ? }
    ? public static void main(String[] args) {
    ??? Sharing2 aaa = new Sharing2();
    ??? aaa.s=new TwoCounter();
    ??? aaa.s.start();//打開TwoCounter線程
    ??? new Watcher(aaa);//打開Watcher線程
    ? }
    }

    上面的注釋講得很清楚了,有可能出現不同步的情況.但奇怪的是,我在運行的時候,卻始終沒有遇到不同步的情況,那么只有一種情況,就是程序中count1++和count2++幾乎是同時進行的,watcher線程插不進來,但是為什么Think in Java上面的程序運行之后就肯定有不同步的情況呢?兩個程序的原理是完全一樣的,唯一不同的是我的程序較為簡單,并且在命令行下運行,未使用GUI.難道是因為使用Applet方式運行或者以Windows主窗口的方式運行開銷更大,使得watcher有機可趁嗎?于是我試著在count1++和count2++之間加了一條循環語句,人為的增大空隙,目的是為了讓watcher好插進來,造成監測出來的count1不等于count2的情況,實現不同步.修改后的程序是這樣的

    ????? ......
    ????? count1++;
    ????? for(int i=0;i<5000;i++);
    ????? count2++;
    ????? ......

    OK!再運行程序,很快就有不同步現象產生了,這似乎證明我剛才的分析是正確的.但奇怪的是,輸出了一次Unsynchrized之后,以后就再也沒有出現了,也就是說,watcher線程只有一次檢測到了兩個計數器count不同.這讓我覺得有點郁悶,是巧合還是必然呢?也許是時間太短了,等下去肯定還會有Unsynchrized輸出的.

    算了,這個問題先放下來,我們繼續.
    既然出現了不同步的問題,那很顯然,解決的方法就是synchronized:將TwoCounter的run方法和SynchTest方法都變成同步方法.這樣做代表什么意思呢? 有什么好處呢?請參考Think in Java的14.2.2節,里面有非常詳盡透徹的闡述.特別是對監視器,也就是我們通常所說的對象鎖的概念,書中講的很清楚.

    總之,需要修改的代碼如下:
    class TwoCounter extends Thread {
    ? public synchronized void run() {
    ??? while (true) {
    ????? count1++;
    ????? count2++;
    ????? System.out.println("Count1="+count1+",Count2="+count2);
    ????? try {
    ??????? sleep(500);
    ????? } catch (InterruptedException e){}
    ?? }
    ? }

    ? public synchronized void synchTest() {
    ??? Sharing2.incrementAccess();
    ??? if(count1 != count2)
    ??????????? System.out.println("Unsynched");//一旦發現不同步,立即顯示
    ? }
    }

    略去其它不寫,表示從問題到解決其實很簡單,呵呵.
    我們注意到無論run()還是synchTest()都是“同步的”。如果只同步其中的一個方法,那么另一個就可以自由忽視對象的鎖定,并可無礙地調用。所以必須記住一個重要的規則:對于訪問某個關鍵共享資源的所有方法,都必須把它們設為synchronized,否則就不能正常地工作。

    現在又遇到了一個新問題。Watcher2永遠都不能看到正在進行的事情,因為整個run()方法已設為“同步”。而且由于肯定要為每個對象運行run(),所以鎖永遠不能打開,而synchTest()永遠不會得到調用。之所以能看到這一結果,是因為accessCount根本沒有變化。

    為解決這個問題,我們能采取的一個辦法是只將run()中的一部分代碼隔離出來。想用這個辦法隔離出來的那部分代碼叫作“關鍵區域”,而且要用不同的方式來使用synchronized關鍵字,以設置一個關鍵區域。Java通過“同步塊”提供對關鍵區域的支持;這一次,我們用synchronized關鍵字指出對象的鎖用于對其中封閉的代碼進行同步。如下所示:

    synchronized(syncObject) {
    ? // This code can be accessed by only
    ? // one thread at a time, assuming all
    ? // threads respect syncObject's lock
    }

    在能進入同步塊之前,必須在synchObject上取得鎖。如果已有其他線程取得了這把鎖,塊便不能進入,必須等候那把鎖被釋放。
    可從整個run()中刪除synchronized關鍵字,換成用一個同步塊包圍兩個關鍵行,從而完成對Sharing2例子的修改。但什么對象應作為鎖來使用呢?那個對象已由synchTest()標記出來了——也就是當前對象(this)!所以修改過的run()方法象下面這個樣子:

    file://注意沒有synchronized關鍵字了
    ? public void run() {
    ??? while (true) {
    ????? synchronized(this){
    ??????? count1++;
    ??????? count2++;
    ????? }
    ????? System.out.println("Count1="+count1+",Count2="+count2);
    ????? try {
    ??????? sleep(500);
    ????? } catch (InterruptedException e){}
    ?? }
    ? }

    file://注意,synchTest()還是要有synchronized關鍵字的,考慮一下為什么

    這樣的話,synchTest方法就可以得到調用了,我們也可以看到accessCount的變化了.

    posted on 2006-11-22 10:13 OMG 閱讀(229) 評論(0)  編輯  收藏 所屬分類: Soket

    <2006年11月>
    2930311234
    567891011
    12131415161718
    19202122232425
    262728293012
    3456789

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    IT風云人物

    文檔

    朋友

    相冊

    經典網站

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 久久免费视频一区| 国产成人va亚洲电影| 免费在线中文日本| 国产AV无码专区亚洲AVJULIA| 春意影院午夜爽爽爽免费| 亚洲精品岛国片在线观看| 深夜A级毛片视频免费| 国产a v无码专区亚洲av| 在线观看片免费人成视频播放| 亚洲精品乱码久久久久久中文字幕| 中文字幕乱码一区二区免费| 亚洲福利视频一区| 亚洲视频免费在线看| 亚洲日本在线电影| 免费大黄网站在线观看| 一级成人a做片免费| 亚洲国产精彩中文乱码AV| 精品无码人妻一区二区免费蜜桃| 亚洲婷婷综合色高清在线| 男男AV纯肉无码免费播放无码 | 亚洲黄色片免费看| 免费可以在线看A∨网站| 亚洲国产成人精品无码区二本| 亚洲?V无码乱码国产精品| 日本免费A级毛一片| 亚洲国产精品张柏芝在线观看| 爽爽日本在线视频免费| 国产免费福利体检区久久| 99久久精品国产亚洲| 99精品全国免费观看视频| 一级特黄录像视频免费| 亚洲精品mv在线观看| 国产午夜影视大全免费观看| 国产午夜精品理论片免费观看| 亚洲午夜电影在线观看高清| 亚洲AV无码专区日韩| 亚洲国产精品免费在线观看| 久久久久亚洲精品无码网址色欲 | 99re热精品视频国产免费| 亚洲乱亚洲乱妇24p| 久久91亚洲人成电影网站|