<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_768_1.html

    我在22號的筆記中不是有一個疑問嗎?為什么我編的程序沒有不同步的現象產生呢,我把它發到csdn上去了,現在我已經基本解決這個問題了,下面是論壇的回復紀錄摘要

    回復人:bluesmile979(笑著) ( ) 信譽:100? 2003-01-22 21:08:00? 得分:0
    說說我的看法,我認為最大的問題在于多線程,看了你的代碼,好像只有兩個線成了。而例子中應該是比較多的線程,多個線程競爭時間片,被打斷的幾率自然就大得多了。就算你加了循環,由于機器的運算速度,仍然沒有多個線程競爭那么現象明顯。不知道各位以為如何。

    回復人:xm4014(forrest) ( ) 信譽:100? 2003-01-22 22:07:00? 得分:0
    to bluesmile979(笑著)
    我也曾經想到過是否因為線程太少而導致,但是我將Think in java的例程中的兩個參數都設為1來運行,那么最后也就和我寫的程序一樣,只有兩個線程,結果照樣有不同步.這又怎么解釋呢

    回復人:tianfeichen(側耳傾聽) ( ) 信譽:110? 2003-01-22 23:57:00? 得分:0
    線程的安排畢竟是隨機的,很少會有不同步的出現,次數少了不容易發現。
    我常用的方法是,先讓無限循環開始,循環的時候也不要求輸出什么的,只加上一個停止的條件,比如:
    if (counter1 != counter2)
    {
    ?? System.out.println(counter1 + " ," + counter2)
    ?? System.exit(0);
    }

    剩下的就是等了,一般十幾秒甚至幾秒就出結果了,可以發現記數已經到幾十萬或者幾百萬了。

    如果同時開了5個線程,等了一分鐘,我就算是它同步了。

    我的方法可能不太科學,不過效果挺好。

    回復人: xm4014(forrest) ( ) 信譽:100? 2003-01-23 11:44:00? 得分:0
    可以幫我調試一下嗎?為什么我按照你的方法卻始終沒有得到結果呢?

    將下面的代碼直接拷貝就可以了,程序名為Sharing2.java,版本是1.4.1

    class TwoCounter extends Thread {
    ? private int count1 = 0, count2 = 0;
    ? private boolean started=false;
    ? public void start(){
    ??? if (!started)
    ??? {
    ????? started=true;
    ????? super.start();
    ??? }
    ? }
    ? public void run() {
    ??? while (true) {
    ??????? count1++;
    ??????? count2++;
    //????? System.out.println("Count1="+count1+",Count2="+count2);
    ????? try {
    ??????? sleep(500);
    ????? } catch (InterruptedException e){System.out.println("TwoCounter.run");}
    ?? }
    ? }

    ? public void synchTest() {
    //??? Sharing2.incrementAccess();
    ??? if(count1 != count2)
    ????? {System.out.println(count1+","+count2);
    ?????? System.exit(0);
    ????? }
    ? }
    }

    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){System.out.println("Watcher.run");}
    ??? }
    ? }
    }

    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();
    ??? new Watcher(aaa);
    ? }
    } ///:~

    另外,根據你的意思,我的程序是沒有問題的,只是線程少了,不同步很難產生,要等到counter增加到很大數目的時候才有可能,對嗎?

    回復人: hey_you(Hey) ( ) 信譽:100? 2003-01-23 13:27:00? 得分:0

    我是這樣想的:不同步而發生沖突是一種可能性,而sychronize是讓這種可能性為0。你沒有1發現不同步,并不能證明永遠都不會發生不同步的情況,那只是一個時間問題。系統對線程的調度受了環境的影響,要是你機器上同時還跑了很多程序,可能情況就不同了。

    回復人: xm4014(forrest) ( ) 信譽:100? 2003-01-23 15:56:00? 得分:0
    呵呵,我用tianfeichen(側耳傾聽)的方法運行的程序,也就是我上面貼的代碼居然有結果了,counter1= 217327,counter2=217356,還真想差的不少。但是時間上絕不是一兩分鐘那么簡單,至少過了兩個小時,可能真是我和他的運行環境的不同造成的.正如hey_you(Hey)所說,只是一個時間問題.

    希望其它人能給出更多的看法,如果覺得沒必要再討論下去,那我就接貼.

    回復人: bluesmile979(笑著) ( ) 信譽:100? 2003-01-23 16:38:00? 得分:0
    我考,一兩個小時你也能堅持,服了。

    我認為問題結果也就兩點了。一個就是我認為的線程數量

    另一個就是你認為的setText會有比較多的處理,占用比較多的資源。

    兩種情況都會影響到這個問題的出現幾率:)樓主宰總結一下吧,呵呵。

    回復人: linliangyi(藍山咖啡) ( ) 信譽:100? 2003-01-23 17:10:00? 得分:0
    sleep(500)占用的時間勝過for(5000)的時間,因此線程在sleep中被切換的概率遠勝于在for中被中斷的概率!!(回頭去看我的程序就知道了)

    事實上,兩個變量從不相等變為相等,正是說明了不同步!!

    順便說一下關于swing和awt控件在線程中操作時,比如setText,常造成很多意外
    樓主可以看看相關的書籍!!

    回復人: xm4014(forrest) ( ) 信譽:100? 2003-01-24 14:25:00? 得分:0
    我將各位的觀點綜合起來總結一下:

    首先要肯定的是,假如不使用synchronized關鍵字來定義同步方法或者定義同步塊,那么,發生不同步的可能是絕對存在的,反過來說,synchronized就是讓這種可能性為0.

    在第一種情況下,發生不同步的可能雖然存在,但是它的幾率受到以下幾個方面因素的影響

    1.在不同的操作系統及運行環境下,捕捉到不同步的幾率可能就不一樣,或者說等待的時間可能就有長有短
    2.程序中線程數目的多寡,如果線程太少,那么這種不同步就難于捕捉到,可能需要等待很長的時間
    3.代碼本身的影響.比如使用awt類中涉及到GUI的方法,可能就會占用較多的資源,造成很多意外,那么發生沖突的可能性就大得多
    4.線程是由操作系統隨機分配的,本來就存在著不確定性,這種不確定性也會影響最后的結果

    不知道是否正確,大家還有什么補充呢?

    明天正式結帖

    不過說實話,我有點搞不懂,為什么最后的結果,counter1(217327)和counter2(217356)會相差那么多呢.按照我的程序,即便watcher線程插到兩個自加的語句中間來,檢測到的這兩個計數器之間的差異頂多也就是1啊.出現這么大的差異,只可能是某一個計數器的自加語句有好多次在根本沒有運行的情況下就被強行中斷了.這就太恐怖了!雖然有其它線程的存在會干擾當前線程,但是也不至于讓當前線程語句不運行吧,最多也就是等等再運行啊?我有點糊涂了,操作系統沒學好,如果大家不嫌麻煩,清幫我解釋一下吧

    結果現在又有新的問題,我想又要等到明天才有答案吧

    但我們今天可以解決另一個涉及到synchronized的問題.這是我在論壇上看到的一個貼子.正是因為我解決不了,我才認為有必要回頭來好好研究線程和同步等內容的.
    問題如下:

    file://分析這段程序,并解釋一下,著重講講synchronized、wait(),notify 謝謝!
    class ThreadA
    {
    ? public static void main(String[] args)
    ? {
    ??? ThreadB b=new ThreadB();
    ??? b.start();
    ??? System.out.println("b is start....");
    ??? synchronized(b)//括號里的b是什么意思,起什么作用?
    ??? {
    ????? try
    ????? {
    ?System.out.println("Waiting for b to complete...");
    ?b.wait();//這一句是什么意思,究竟讓誰wait?
    ??????? System.out.println("Completed.Now back to main thread");
    ????? }catch (InterruptedException e){}
    ??? }
    ??? System.out.println("Total is :"+b.total);
    ?? }
    }

    class ThreadB extends Thread
    {
    ? int total;
    ? public void run()
    ? {
    ??? synchronized(this)
    ??? {
    ????? System.out.println("ThreadB is running..");
    ????? for (int i=0;i<100;i++ )
    ????? {
    ??????? total +=i;
    ??????? System.out.println("total is "+total);
    ????? }
    ????? notify();
    ??? }
    ? }
    }

    要分析這個程序,首先要理解notify()和wait(),為什么在前幾天紀錄線程的時候沒有紀錄這兩個方法呢,因為這兩個方法本來就不屬于Thread類,而是屬于最底層的object基礎類的,也就是說不光是Thread,每個對象都有notify和wait的功能,為什么?因為他們是用來操縱鎖的,而每個對象都有鎖,鎖是每個對象的基礎,既然鎖是基礎的,那么操縱鎖的方法當然也是最基礎了.

    再往下看之前呢,首先最好復習一下Think in Java的14.3.1中第3部分內容:等待和通知,也就是wait()和notify了.

    按照Think in Java中的解釋:"wait()允許我們將線程置入“睡眠”狀態,同時又“積極”地等待條件發生改變.而且只有在一個notify()或notifyAll()發生變化的時候,線程才會被喚醒,并檢查條件是否有變."

    我們來解釋一下這句話.

    "wait()允許我們將線程置入“睡眠”狀態",也就是說,wait也是讓當前線程阻塞的,這一點和sleep或者suspend是相同的.那和sleep,suspend有什么區別呢?

    區別在于"(wait)同時又“積極”地等待條件發生改變",這一點很關鍵,sleep和suspend無法做到.因為我們有時候需要通過同步(synchronized)的幫助來防止線程之間的沖突,而一旦使用同步,就要鎖定對象,也就是獲取對象鎖,其它要使用該對象鎖的線程都只能排隊等著,等到同步方法或者同步塊里的程序全部運行完才有機會.在同步方法和同步塊中,無論sleep()還是suspend()都不可能自己被調用的時候解除鎖定,他們都霸占著正在使用的對象鎖不放.

    而wait卻可以,它可以讓同步方法或者同步塊暫時放棄對象鎖,而將它暫時讓給其它需要對象鎖的人(這里應該是程序塊,或線程)用,這意味著可在執行wait()期間調用線程對象中的其他同步方法!在其它情況下(sleep啊,suspend啊),這是不可能的.

    但是注意我前面說的,只是暫時放棄對象鎖,暫時給其它線程使用,我wait所在的線程還是要把這個對象鎖收回來的呀.wait什么?就是wait別人用完了還給我啊!

    好,那怎么把對象鎖收回來呢?

    第一種方法,限定借出去的時間.在wait()中設置參數,比如wait(1000),以毫秒為單位,就表明我只借出去1秒中,一秒鐘之后,我自動收回.

    第二種方法,讓借出去的人通知我,他用完了,要還給我了.這時,我馬上就收回來.哎,假如我設了1小時之后收回,別人只用了半小時就完了,那怎么辦呢?靠!當然用完了就收回了,還管我設的是多長時間啊.

    那么別人怎么通知我呢?相信大家都可以想到了,notify(),這就是最后一句話"而且只有在一個notify()或notifyAll()發生變化的時候,線程才會被喚醒"的意思了.

    因此,我們可將一個wait()和notify()置入任何同步方法或同步塊內部,無論在那個類里是否準備進行涉及線程的處理。而且實際上,我們也只能在同步方法或者同步塊里面調用wait()和notify().

    這個時候我們來解釋上面的程序,簡直是易如反掌了.

    synchronized(b){...};的意思是定義一個同步塊,使用b作為資源鎖。b.wait();的意思是臨時釋放鎖,并阻塞當前線程,好讓其他使用同一把鎖的線程有機會執行,在這里要用同一把鎖的就是b線程本身.這個線程在執行到一定地方后用notify()通知wait的線程,鎖已經用完,待notify()所在的同步塊運行完之后,wait所在的線程就可以繼續執行.

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

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

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    IT風云人物

    文檔

    朋友

    相冊

    經典網站

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产亚洲漂亮白嫩美女在线| 在线免费观看毛片网站| 特级毛片A级毛片免费播放| 亚洲日韩中文字幕| 好看的电影网站亚洲一区| 亚洲欧洲日产国码一级毛片| 午夜视频免费观看| 日韩精品无码区免费专区 | 国产精品美女自在线观看免费 | 午夜亚洲国产理论秋霞| 久久精品国产亚洲5555| 免费一级黄色毛片| 永久免费毛片手机版在线看| 成人免费的性色视频| 18观看免费永久视频| 男人的天堂网免费网站| 中文在线观看永久免费| 一级a性色生活片久久无少妇一级婬片免费放 | 亚洲AV人人澡人人爽人人夜夜| 久久久久久A亚洲欧洲AV冫| 国产一级一片免费播放i| 全免费a级毛片免费看不卡| 青春禁区视频在线观看直播免费| 777爽死你无码免费看一二区| APP在线免费观看视频| 中文永久免费观看网站| eeuss影院免费92242部| 五月天国产成人AV免费观看| 色费女人18女人毛片免费视频| 色欲aⅴ亚洲情无码AV蜜桃| 亚洲av无码专区首页| 亚洲精品无码成人| 亚洲精华液一二三产区| 亚洲第一综合天堂另类专| 亚洲国产精品久久久久秋霞小| 亚洲熟伦熟女专区hd高清| 亚洲精品自偷自拍无码| 久久亚洲精品高潮综合色a片| 久久精品熟女亚洲av麻豆| 国产亚洲情侣久久精品| 国产AV日韩A∨亚洲AV电影|