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

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

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

    狂奔 lion

    自強不息

    2010年7月7日

    淺談Java中的同步的方法和原理

    Java的內存模型中Thread會附有自己的堆棧,寄存器,必要時需要和主存即heap之間同步。
    可以使用Synchornized關鍵字和Concurrent包中的Lock可以保證線程互斥和可見性。

    互斥性體現在類鎖或者對象鎖上,每個對象自身都包含一個監視器,該監視器是一個每次只能被一個線程所獲取進入的臨界區,可以通過wait和notify來退出和準入臨界區。可以看出這是一個生產者-消費者的模型。而Concurrent包中的Lock為了能夠獲得更好的性能和更好的擴展性,以及不依賴于關鍵字的可讀代碼,自己實現了這樣一個生產消費隊列,也就是AbstractQueuedSynchronizer,被稱為AQS的機制。每個Lock都內置了一個AbstractQueuedSynchronizer。需要說明的是AbstractQueuedSynchronizer內部實現采用了CAS機制,通過getState, setState, compareAndSetState訪問控制一個32bit int的形式進行互斥。

    那么可見性是如何保證的呢?

    對于關鍵字的同步機制,其實可見性就是線程和主存之間的同步時機問題。共有4個時間點需要注意:
    1 獲取或釋放類鎖/對象鎖的時候。Thread保證reload/flush全部變更
    2 volatile就是flush on write或者reload on read
    3 當線程首次訪問共享變量時,可以得到最新的結果。
    題外:所以在構造方法中公布this時很危險的。簡單的說,就是構造時不逃脫任何變量,不開啟新的線程,只做封裝。關于安全構造,請參考
    http://www.ibm.com/developerworks/cn/java/j-jtp0618/#resources
    4 線程結束時,所有變更會寫回主存

    關于Concurrent Lock如何實現可見性的問題,Doug Lea大俠,只在他的論文中提到,按照JSR133,Unsafe在getState, setState, compareAndSetState時保證了線程的變量的可見性,不需要額外的volatile支持,至于具體這些native做了哪些magic就不得而知了,總之,最后的contract就是保證lock區間的共享變量可見性。開發團隊被逼急了就這樣回答:
    There seems to be a real reluctance to explain the dirty details. I think the question was definitely understood on the concurrent interest thread, and the answer is that synchronized and concurrent locking are intended to be interchangable in terms of memory semantics when implemented correctly. The answer to matfud's question seems to be "trust us.”

    不過這個地方的確是開發團隊給我們用戶迷惑的地方,在同樣應用了CAS機制的Atomic類中,都內嵌了volatile變量,但是再lock塊中,他告訴我們可以保證可見性。

    感興趣的同學可以下面的兩個thread和Doug Lea的thesis:
    http://altair.cs.oswego.edu/pipermail/concurrency-interest/2005-June/001587.html
    http://forums.sun.com/thread.jspa?threadID=631014&start=15&tstart=0
    http://gee.cs.oswego.edu/dl/papers/aqs.pdf

    posted @ 2010-07-09 19:49 楊一 閱讀(1859) | 評論 (0)編輯 收藏

    commons-net FTPClient API存取設計

    文件系統無非就是文件的存取和組織結構。
    訪問一個文件系統的API也應該是寫,讀,定位方法(Pathname?/URI?)

    FTPClient針對文件的保存和獲取各提供了兩個方法,分別是:

    public boolean storeFile(String remote, InputStream local)
    public OutputStream storeFileStream(String remote)

    public boolean retrieveFile(String remote, OutputStream local)
    public InputStream retrieveFileStream(String remote)

     

    兩個方法貌似相同,實際不同,返回流的那個因為不能馬上處理流,所以需要用戶手工調用completePendingCommand,而另一個傳遞流進去的則不需要。可能有同學已經遇到過這個問題了,讀寫第一個文件時總是正確的,當相同API讀寫第二個文件時,block住了。這是因為FTPClient要求在進行流操作之后執行completePendingCommand,以確保流處理完畢,因為流處理不是即時的,所以也沒有辦法不手工調用completePendingCommand。問題是開發者把不返回流的方法末尾加上了completePendingCommand,如果不看代碼可能根本不知道。
    文檔上說:

         * There are a few FTPClient methods that do not complete the
         
    * entire sequence of FTP commands to complete a transaction.  These
         
    * commands require some action by the programmer after the reception
         
    * of a positive intermediate command.  After the programmer's code
         * completes its actions, it must call this method to receive
         
    * the completion reply from the server and verify the success of the
         
    * entire transaction.


    但是這樣仍然還是讓人有點困惑,為什么都是存儲/讀取的方法,有時候要調用completePendingCommand,有時候不調用?更嚴重的問題是completePendingCommand調用了getReply,如果一個命令通過socket stream傳了過去但是沒有getReply,即沒有completePendingCommand,那么下次發命令時,將會受到本次返回碼的干擾,得到無效的響應。而如果在completePendingCommand之后又進行了一次無辜的completePendingCommand,那么因為FTP Server上沒有Reply了,就會block。所以completePendingCommand并不是可以隨意添加的。

    現在出現了兩個問題:
    1 completePendingCommand很容易多出來或遺漏
    2 顯式調用completePendingCommand暴露了底層實現,給用戶帶來不便,用戶只想要InputStream或者OutputStream

    為了解決這個問題,可以對InputStream進行擴展,建立一個ReplyOnCloseInputStream,如下:

    private static ReplyOnCloseInputStream extends InputStream{
      
    //
      public ReplyOnCloseInputStream(InputStream is, FTPClient c){
        
    //
      }

      
    //
      @override
      
    public void close(){
        
    if(c.completePendingCommand){
          is.close();
        }
    else{
          
    //throw Exception
        }

      }

    }
     
    //
    return new ReplyOnCloseInputStream(is, client);


    這樣封裝之后,FTPClient的用戶只需要正常在處理完流之后關閉即可,而不必暴露實現細節。保存文件也可以用相同的方法封裝OutputStream。

    posted @ 2010-07-07 23:08 楊一 閱讀(3464) | 評論 (1)編輯 收藏

    <2010年7月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    公告

    本人在blogjava上發表的文章及隨筆除特別聲明外均為原創或翻譯,作品受知識產權法保護并被授權遵從 知識分享協議:署名-非商業性使用-相同方式共享 歡迎轉載,請在轉載時注明作者姓名(楊一)及出處(www.tkk7.com/yangyi)
    /////////////////////////////////////////
    我的訪問者

    常用鏈接

    留言簿(5)

    隨筆分類(55)

    隨筆檔案(55)

    相冊

    Java

    其他技術

    生活

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    自強不息


    用心 - 珍惜時間,勇于創造
    主站蜘蛛池模板: 人妻仑刮八A级毛片免费看| 亚洲精品人成网在线播放影院| 亚洲国产欧美国产综合一区| 亚洲免费中文字幕| 亚洲国产日韩在线一区| 久久国产免费福利永久| 亚洲国产精品白丝在线观看| 免费国产成人高清在线观看网站| 亚洲一区二区三区不卡在线播放| 野花高清在线观看免费3中文| 精品国产成人亚洲午夜福利| 国产免费久久精品| 一个人免费观看日本www视频 | 亚洲成人免费网址| 青青青免费国产在线视频小草| 亚洲日韩乱码久久久久久| 性盈盈影院免费视频观看在线一区| 亚洲欧美日韩中文二区| 日产国产精品亚洲系列| 久久九九免费高清视频| 亚洲高清在线播放| a毛片基地免费全部视频| 色综合久久精品亚洲国产| 亚洲无码精品浪潮| 久9热免费精品视频在线观看| 亚洲精品国产精品国自产网站| 国产高清免费的视频| 中文在线观看国语高清免费| 久久亚洲精品中文字幕| 日本免费人成黄页网观看视频| 久久一区二区三区免费| 亚洲精品国产成人中文| 日本免费电影一区| 久久久久久久99精品免费观看| 精品日韩99亚洲的在线发布| 亚洲精品岛国片在线观看| 91免费福利精品国产| 免费无码国产在线观国内自拍中文字幕 | 精品无码一区二区三区亚洲桃色| 黄网址在线永久免费观看 | 永久免费毛片手机版在线看|