posts - 403, comments - 310, trackbacks - 0, articles - 7
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

               摘要: 以下簡單的整理來自游俠 netshow論壇的帖子 部分補充  閱讀全文

          posted @ 2008-04-13 11:30 ZelluX 閱讀(1057) | 評論 (1)編輯 收藏

               摘要: 問題:
          給定n個32位無符號整數,求出其中異或結果最大的兩個整數。  閱讀全文

          posted @ 2008-04-10 00:33 ZelluX 閱讀(4655) | 評論 (5)編輯 收藏

          轉載請注明 作者 ZelluX??? http://www.aygfsteel.com/zellux

          看OOP教材時,提到了一個雙檢測鎖定(Double-Checked Lock, DCL)的問題,但是書上沒有多介紹,只是說這是一個和底層內存機制有關的漏洞。查閱了下相關資料,對這個問題大致有了點了解。

          從頭開始說吧。

          在多線程的情況下Singleton模式會遇到不少問題,一個簡單的例子

          ?? 1:? class Singleton {?????
          ?? 2:????? private static Singleton instance = null;?????
          ?? 3:????????
          ?? 4:????? public static Singleton instance() {?????
          ?? 5:????????? if (instance == null) {?????
          ?? 6:????????????? instance = new Singleton();?????
          ?? 7:????????? }?????
          ?? 8:????????? return instance;????
          ?? 9:????? }????
          ?? 10:? }

          ??
          假設這樣一個場景,有兩個線程調用Singleton.instance(),首先線程一判斷instance是否等于null,判斷完后一瞬間虛擬機把線程二調度為運行線程,線程二再次判斷instance是否為null,然后創建一個Singleton實例,線程二的時間片用完后,線程一被喚醒,接下來它執行的代碼依然是instance = new Singleton();
          兩次調用返回了不同的對象,出現問題了。

          最簡單的方法自然是在類被載入時就初始化這個對象:private static Singleton instance = new Singleton();

          JLS(Java Language Specification)中規定了一個類只會被初始化一次,所以這樣做肯定是沒問題的。

          但是如果要實現延遲初始化(Lazy initialization),比如這個實例初始化時的參數要在運行期才能確定,應該怎么做呢?

          依然有最簡單的方法:使用synchronized關鍵字修飾初始化方法:

          ??? public synchronized static Singleton instance() {???????
          ??????? if (instance == null) {
          ??????????? instance = new Singleton();
          ??????? }
          ??????? return instance;
          ??? }

          ???
          這里有一個性能問題:多個線程同時訪問這個方法時,會因為同步而導致每次只有一個線程運行,影響程序性能。而事實上初始化完畢后只需要簡單的返回instance的引用就行了。

          DCL是一個“看似”有效的解決方法,先把對應代碼放上來吧:

          ??? 1 :?? class Singleton {??
          ??? 2 :?????? private?static?Singleton instance = null ;??
          ??? 3 :?????
          ??? 4 :?????? public?static Singleton instance() {??
          ??? 5 :?????????? if?(instance?== null ) {
          ??? 6 :?????????????? synchronized?(this) {??
          ??? 7 :?????????????????? if?(instance?==?null)
          ??? 8 :????????????????????? instance = new?Singleton();
          ??? 9 :????????????? }
          ??? 10 :????????? }
          ??? 11 :??????????return instance;
          ??? 12 :????? }
          ??? 13 :? }

          用JavaWorld上對應文章的標題來評論這種做法就是smart, but broken。來看原因:

          Java編譯器為了提高程序性能會進行指令調度,CPU在執行指令時同樣出于性能會亂序執行(至少現在用的大多數通用處理器都是out-of-order的),另外cache的存在也會改變數據回寫內存時的順序[2]。JMM(Java Memory Model, 見[1])指出所有的這些優化都是允許的,只要運行結果和嚴格按順序執行所得的結果一樣即可。

          Java假設每個線程都跑在自己的處理器上,享有自己的內存,和共享的主存交互。注意即使在單核上這種模型也是有意義的,考慮到cache和寄存器會保存部分臨時變量。理論上每個線程修改自己的內存后,必須立即更新對應的主存內容。但是Java設計師們認為這種約束會影響程序性能,他們試著創造了一套讓程序跑得更快、但又保證線程之間的交互與預期一致的內存模型。

          synchronized關鍵字便是其中一把利器。事實上,synchronized塊的實現和Linux中的信號量(semaphore)還是有區別的,前者過程中鎖的獲得和釋放都會都會引發一次Memory Barrier來強制線程本地內存和主存之間的同步。通過這個機制,Java中的同步機制保證了synchronized塊中指令的原子性(atomic)。

          好了,回過頭來看DCL問題。看起來訪問一個未同步的instance字段不會產生什么問題,我們再次來假設一個場景:

          線程一進入同步塊,執行instance = new Singleton(); 線程二剛開始執行getResource();

          按照順序的話,接下來應該執行的步驟是 1) 分配新的Singleton對象的內存 2) 調用Singleton的構造器,初始化成員字段 3) instance被賦為指向新的對象的引用。

          前面說過,編譯器或處理器都為了提高性能都有可能進行指令的亂序執行,線程一的真正執行步驟可能是1) 分配內存 2) instance指向新對象 3) 初始化新實例。如果線程二在2完成后3執行前被喚醒,它看到了一個不為null的instance,跳出方法體走了,帶著一個還沒初始化的Singleton對象。

          錯誤發生的一種情形就是這樣,關于更詳細的編譯器指令調度導致的問題,可以參看這個網頁 [4]。

          [3] 中提供了一個編譯器指令調度的證據

          instance = new Singleton(); 這條命令在Symantec JIT中被編譯成

          0206106A?? mov???????? eax,0F97E78h
          0206106F?? call??????? 01F6B210????????????????? ; 分配空間
          02061074?? mov???????? dword ptr [ebp],eax?????? ; EBP中保存了instance的地址

          02061077?? mov???????? ecx,dword ptr [eax]?????? ; 解引用,獲得新的指針地址

          02061079?? mov???????? dword ptr [ecx],100h????? ; 接下來四行是inline后的構造器
          0206107F?? mov???????? dword ptr [ecx+4],200h???
          02061086?? mov???????? dword ptr [ecx+8],400h
          0206108D?? mov???????? dword ptr [ecx+0Ch],0F84030h

          可以看到,賦值完成在初始化之前,而這是JLS允許的。
          ?
          另一種情形是,假設線程一安穩地完成Singleton對象的初始化,退出了同步塊,并同步了和本地內存和主存。線程二來了,看到一個非空的引用,拿走。注意線程二沒有執行一個Read Barrier,因為它根本就沒進后面的同步塊。所以很有可能此時它看到的數據是陳舊的。

          還有很多人根據已知的幾種提出了一個又一個fix的方法,但最終還是出現了更多的問題。可以參閱[3]中的介紹。

          [5]中還說明了即使把instance字段聲明為volatile還是無法避免錯誤的原因。

          由此可見,安全的Singleton的構造一般只有兩種方法,一是在類載入時就創建該實例,二是使用性能較差的synchronized方法。

          (by ZelluX? http://www.aygfsteel.com/zellux )

          參考資料:

          [1] Java Language Specification, Second Edition, 第17章介紹了Java中線程和內存交互關系的具體細節。
          [2] out-of-order與cache的介紹可以參閱Computer System, A Programmer's Perspective的第四、五章。
          [3] The "Double-Checked Locking is Broken" Declaration, http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
          [4] Synchronization and the Java Memory Model, http://gee.cs.oswego.edu/dl/cpj/jmm.html
          [5] Double-checked locking: Clever, but broken, http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html?page=1
          [6] Holub on Patterns, Learning Design Patterns by Looking at Code

          ?

          posted @ 2008-04-07 21:58 ZelluX 閱讀(2324) | 評論 (7)編輯 收藏

          感冒發燒。

          把不應該存在的博文全刪了。

          我知道我在和自己賭氣。

          那又如何。

          回過頭來,這兩年我所得到的,不過是可以隨手扔掉的東西。

          最后,acm的那些人們加油。

          posted @ 2008-04-06 14:05 ZelluX 閱讀(337) | 評論 (3)編輯 收藏

          翹課大半,作業一半不交一半抄,總之太不像學生了。
          搞得現在Super Scalar都只知道個大概,tableaux也知其然而不知所以然。
          下星期好好參與一次,上課、作業一個都不能少,恩。
          至于之后么,再說咯。

          posted @ 2008-04-04 15:33 ZelluX 閱讀(401) | 評論 (0)編輯 收藏

          沒事干找了幾個SICP上的習題做,先是一道以前只想出一種很啰嗦的寫法的題目

          Ex 2.18
          把一個列表倒過來。不習慣在lisp里用iterative方式 >,<

          接下來幾題都是Map-Reduce思想的應用(或者照書上的說法,用enumerator - filter - map - accumulator這四個步驟操作一個list)

          用到的幾個函數:

          enumrate-tree 的功能是遍歷一個樹狀結構,把其中的所有葉子保存在一個list中。

          Ex 2.34
          利用Horner's rule計算多項式結果(這公式這幾天還經常碰到)

          Ex 2.35
          數出一棵樹中的葉子數。這題我的做法比較土,沒想到map-reduce操作上的遞歸,而是把葉子節點的值都改成1然后一個累加。

          其實只要遞歸調用主函數就行了

          Ex 2.36
          可以理解為計算矩陣各列之和吧


          > (accumulate-n + 0 (list (list 1 2 3) (list 4 5 6) (list 7 8 9) (list 10 11 12)))
          (22 26 30)

          posted @ 2008-04-03 22:33 ZelluX 閱讀(1100) | 評論 (0)編輯 收藏

          這語言真不錯,不像Java那么呆,可惜不開源。
          入門看的書是CLR via C#中文版,翻譯質量不錯,起碼到現在還沒覺得有必要翻一翻原版(不過為什么中文書都喜歡把“棧”叫成“堆棧”呢)。
          前面幾章粗略看了下,從第四章類型基礎開始重點閱讀。
          繼續漫無目的的學習感興趣的東西,學習之中經常會驚喜的發現,自己看問題的角度已經不同于之前了。

          1. 類的new操作會遞歸調用該類的所有父類構造器,直到System.Object,后者的構造器只是簡單返回,用ILDasm查看MSCorLib.dll可以證實這一點。

          2. is和as操作符,is類似于Java中的instanceof,as會先檢查類型,如果兼容返回該對象的引用,反之返回null。
          Emplooee?e?=?o?as?Employee;
          if?(e?!=?null)?{
          ????
          //?blah
          }
          利用as可以做到只檢驗一次對象類型,提高程序性能。這本書的很多地方都提到了性能因素。

          3. 方法調用和x86上匯編語言調用機制很類似。先是參數入棧,接著返回地址入棧,返回的時候也差不多。不知道x64等寄存器較多的架構上會不會使用寄存器傳參呢,呵呵。

          4. 作為方法的prologue的一部分,CLR會自動將所有局部變量初始化為null或0。感覺這個自動初始化沒什么必要,在第五章可以看到。
          SomeVal?v1;
          SomeVal?v1?
          =?new?SomeVal();
          這里的SomeVal都是值類型,CLR都會將它們初始化為0。區別在于C#認為前者沒有初始化,直接使用這個值會報錯;而后者在不賦值的情況下使用這個值。
          可能這是CLR和C#之間不統一導致的冗余步驟吧。

          5. CLR開始在一個進程中運行時,會給System.Type類型創建一個實例,每個類都會包含指向System.Type類型的指針。

          6. CLR提供了執行溢出檢查的計算指令,例如add.ovf對應add,mul.ovf對應mul。C#中默認關閉溢出檢查。
          可以使用checked關鍵字使用溢出檢查。一般情況下,對預計可能發生溢出的代碼放到checked塊中,對允許溢出的代碼(比如計算hash值)放到一個unchecked塊中,其他情況,Debug時打開編譯器的/checked+開關,Release版本關閉。

          7. 所有的值類型都是從System.ValueType繼承的。后者重寫了Equals方法,比較兩個值對象是否完全相等。

          8. boxing和unboxing。
          boxing:托管堆中分配內存,復制值類型,然后返回對象地址。
          unboxing:相當于一個通過指針取值的過程,不過這個指針是已裝箱部分中的實際值部分。

          9. FCL(Framework Class Library)中包含了支持值類型的泛型容器類,不需要對容器中的元素進行boxing/unboxing處理。
          不過這里就有個問題了,值類型的話是放在棧上的,生命周期小于容器的,這個怎么處理呢?
          第16章才詳細解釋泛型,先把這個問題留著吧 =,=

          10. 依然是性能問題。有時候編譯器會反復對一個值類型boxing,此時手動boxing會提高一些性能。
          Int32?v?=?5;
          //?需三次boxing
          Console.WriteLine("{0},?{1},?{2}",?v,?v,?v);

          //?只需一次boxing
          Object?o?=?v;
          Console.WriteLine(
          "{0},?{1},?{2}",?o,?o,?o);

          接下來書上舉了個很搞的例子說明boxing和unboxing的各種情況,其實也很容易理解。

          posted @ 2008-04-02 23:33 ZelluX 閱讀(1548) | 評論 (14)編輯 收藏

          ??? 火車緩緩地開著,混雜的人群。此時的我不屬于兩邊世界中的任何一個,孤立于這種空間和從屬感的交界處。理下思路,趁著記憶的新鮮,在手機上敲下這四天的感受,以彌補將來的某天可能發生的對這次旅行的淡忘。

          Zijingang Campus: A Fudaner's Perspective

          1. Abstract
          一次課堂電影(話劇《暗戀桃花源》[5])
          旁聽兩節課,圖形學和線性代數。圖形學課上回答一次問題 =_=
          一場越劇,小百花越劇團的《春琴傳》
          一場話劇,黑白劇社[1]的《我在天堂等你》[2]
          半天圖書館自修,讀了半章SICP[4]和一篇paper
          半天機房灌水,水木C版版主上任后的第一個操作居然是在浙大完成的
          半天在“風雨操場”打球
          一晚上在浙大戰網打了十盤星際,九勝一負

          2. Introduction
          ??? K900到車管所,一站的路程后到達正門。紫金港的正門沒有試圖制造一種空間隔離感,寬敞的道路上橫躺著一塊刻有“浙江大學”的石塊,構成了形式上的正門。步行百余部后,回頭才意識到原來百余步前的所處位置竟是一個入口。
          ??? 這個入口給人一種寬廣、松馳的感覺,與復旦的正門放置偉人像不同,紫金港的封面很平坦。除了草坪就無其他,可以望到天際。整個紫金港都給我這樣的感覺:草坪、樹、湖的世界中,點綴著幾幢風格各異的建筑。

          3. Details
          3.1 上課
          ??? 其實到浙大吃完飯后做的第一件事就是旁聽了一節數媒專業的圖形學,上的是三維空間的坐標變換。老師上課進度偏慢,絕大部分學生上課都很認真。感到那么一點點的壓力 >,<

          3.2 圖書館
          ??? 一直覺得圖書館是大學的靈魂組成部分之一。甚至大一的時候覺得有個好的圖書館和一套優秀的借閱制度就足以成為一個好的大學了。也因此新到一個大學后總是特別關注那里的圖書館。
          ??? 紫金港圖書館依傍在高聳的行政樓旁,可以把它比成計算中心,行政樓對應于光華主樓,較之后者它們靠得更緊密些。浙大同學說外校同學來看圖書館時,第一反應總是誤把行政樓當圖書館。喜歡圖書館的這種低調。
          ??? 圖書館的書架分類很籠統,所有的理工類書櫥都被貼上了“自然科學”的標簽,恐怕找書的時候要很依賴電腦。抽樣調查了計算機類書籍,書目較小,重復率較大,甚至會有十幾冊同本書罷占一層書架的情況。閱讀環境很不錯,落地窗,明亮。窗外便是那片湖,一如圖書館般地平靜。若是把座椅換成搖椅,再加上一杯咖啡,最愉悅的享受莫過于此。
          ??? 離開圖書館時還讓同學代借了本SICP[4],本想帶回上海以此要脅該同學五一來復旦,到時候再還的。無奈多帶本書太麻煩,回來之前還是還掉了。

          3.3 付費
          ??? 住宿樓旁有幾家小吃店,其中不少店都是設置了一個單獨的付費窗,而這個付費機制里沒有任何憑證,或者說點了吃的卻不付錢是很容易做到。別的不多說,這樣一種店與客之間的信任給人一種親切感。當然這也和紫金港地理位置較偏遠,外人較少有關。

          3.4 話劇
          ??? 看了黑白劇社[1]的《我在天堂等你》[2]。話劇在一個可容納百人左右的小書屋里進行。由于一個月前剛看過人藝的《榆樹下的欲望》[3],相比之下學生的功底自然略遜一籌,尤其是對老年人的刻劃上。不過總體還是很不錯的。
          ??? 記憶最深的是社員的那份激情,話劇結束后,演員和工作人員挨個自我介紹完畢,然后跑出書屋,站在門口等待出來的觀眾,齊喊“再見”“謝謝”。下樓走出百余米后,聽到后面三聲擊掌,接著是社員們高喊“謝謝你們”,如此重復幾遍,一陣高過一陣。被這種熱情所震撼。

          3.5 肆
          ??? 一位同學的寢室門口貼著一張記錄著這個班級同學的奮斗目標之類的墻紙,中間是一個碩大的草體“肆”。奮斗目標都很直接,譬如要被Stanford商學院錄取,要進入某某大公司云云。不怎么喜歡這種過于外露的上進心,更欣賞復旦略帶散漫的風格。

          3.6 還是課
          ??? 浙大課比較多。上下午各5節,每節45分鐘,中間休息5/15分。同時周末有課也是很常見的現象,為了提高績點而重修的同學通常周末的課表也很滿。個人不喜歡這種課多的生活,喜歡興趣驅動的學習,不喜歡自己的學習方向太受外力的牽引。

          4. The End
          ??? 總是有一種聲音提醒自己,我不屬于這里,注定不屬于。太多的不應該出現的巧合,太多的主觀的或是客觀的借口。我有自己的天地,那里與浙大沒有交集,即便我希望會有。

          5. Acknowledgements
          ??? 感謝浙大那些被我折騰、蹭吃蹭喝的同學。
          ??? 感謝版主的m或b。

          6. References
          [1] 黑白劇社 http://www.qsc.zju.edu.cn/heibai/
          [2] 我在天堂等你 http://www.douban.com/subject/1310322/
          [3] 榆樹下的欲望 Desire Under the Elms, http://www.douban.com/subject/1297393/
          [4] Structure and Interpretation of Computer Programs, http://www.douban.com/subject/1451622/
          [5] 暗戀桃花源,富含搞笑因素卻又錯綜復雜值得深深體味的一部話劇,推薦一看 http://www.douban.com/subject/1299889/
          [6] 春琴傳,較傳統的日本愛情故事 http://www.douban.com/subject/1949657/

          posted @ 2008-03-31 21:18 ZelluX 閱讀(574) | 評論 (1)編輯 收藏

          其實理解了?Regular Expression?-> NFA -> DFA 這個過程,大致的復雜度確定也不難

          發信人: styc (styc), 信區: Algorithm
          標? 題: Re: 請問一下大家正則表達式的時間復雜度
          發信站: 水木社區 (Wed Mar 26 20:37:02 2008), 站內

          NFA構造O(n),匹配O(nm)
          DFA構造O(2^n),最小化O(kn'logn')(N'=O(2^n)),匹配O(m)
          n=regex長度,m=串長,k=字母表大小,n'=原始的dfa大小
          大概是這樣子吧

          posted @ 2008-03-27 00:21 ZelluX 閱讀(1693) | 評論 (0)編輯 收藏

          試試Google Document


          posted @ 2008-03-26 17:01 ZelluX 閱讀(418) | 評論 (0)編輯 收藏

          僅列出標題
          共39頁: First 上一頁 2 3 4 5 6 7 8 9 10 下一頁 Last 
          主站蜘蛛池模板: 克山县| 万源市| 广饶县| 定结县| 昌黎县| 杭州市| 洱源县| 利津县| 岱山县| 土默特右旗| 神池县| 运城市| 普洱| 高州市| 五大连池市| 高邮市| 正安县| 炎陵县| 张家川| 周口市| 鄯善县| 郧西县| 贺兰县| 静安区| 南澳县| 屏东县| 岱山县| 马关县| 赞皇县| 芦溪县| 蕲春县| 梁河县| 本溪| 安平县| 桓台县| 新沂市| 深州市| 博客| 定西市| 福海县| 白水县|