文章目錄
上一篇我們大致的瞭解了幾種聊天室的行為模式
最簡單明了的推模式 幾乎不需要任何多餘的語言來描述它的實現
這一篇我們看看如何?拉模式更有效。
本圖清晰的表現了"拉"模式聊天室的行為。
- 並發多使用者向資料池寫資料
- 並發多使用者從資料池讀書據
- 資料最好以時間為順序儲存在集合中
- 某時間向後的枚舉尋找將是最大的消耗。
聊天室進化 -女僕編年史神秘的原始社會
仍然參考我們神奇樸素的Asp3聊天室
53 Application.lock
54 Application("show5")=Application("show4") '一條新資訊駕到 第五條資訊被淘汰
55 Application("show4")=Application("show3")
56 Application("show3")=Application("show2")
57 Application("show2")=Application("show")
58 Application("show")=NewMessage '其他所有的資訊向前移動一次給新的資訊讓個位置。
59 Application.UnLock
60 Response.Write Application("show5")
61 Response.Write Application("show4") '由於是postback 模式 必須輸出曆史n行資料
62 Response.Write Application("show3")
63 Response.Write Application("show2")
64 Response.Write Application("show")
從安全執行緒角度來說 本來 response.write應該也在 application .lock 塊中 或者分開兩個lock塊. 但是這裡由於response.write 在非cache模式下可能帶來的時間延遲 作者煞費苦心的把他們從安全鎖中移動出來.在實際運行中 很可能出現丟話或者重複發言的狀況
application究竟 被人做了些什嗎? 沒有邊界 沒有抽象封裝的這個實現就好像原始共產主義 誰是誰的誰啊這都是!
私人制出現,奴隸社會 LOCK~ 這個女奴是我的~
翻譯成c# 我們可以看到一個比較容易理解的邏輯 當然這個代碼稍微有所修改 兩個鎖很明確 很完美的把資料和線程排起了隊伍
Code Snippet
- class Channel
- {
- Queue<string> MessageQ = new Queue<string>();
-
- public void Say(string message) //寫資訊
- {
- lock (MessageQ)
- {
- MessageQ.Enqueue(message);
- while (MessageQ.Count > 5) // 刪多餘
- {
- MessageQ.Dequeue();
- }
-
- }
- }
-
- public string[] Listen() //\u-28781 ?出所有
- {
- lock (MessageQ)
- {
- return MessageQ.ToArray();
-
- }
-
- }
-
- }
在aspx可能這樣調用
Code Snippet
- Channel cr = session["Chat"];
- cr.Say(Request["text"]);
-
- foreach (var s in cr.Listen())
- {
- Response.write("<p>");
- Response.write(s);
- Response.write("</p>");
- }
看起來圓滿完成任務 但是裡面充滿了曖昧
類似事務 或者訪問非託管資源 在訪問線程臨界資源的時候有個原則
你儘可能的晚鎖 儘可能的早釋放,
看看剛剛做了些什麼
Oh My God
我們可憐的Channel阿 他被全程鎖定。好像一個被老爺少爺輪流調教的女奴啊,真讓我等正人君子心潮澎湃~~ 啊不對 是於心不忍。
由於每個調教者在調教前聲明:這個女奴是“我雷瓦Mono”我的東西! 所以在調教者聲明 這個女僕“亞沒漏”不要了之前 誰也不許碰!
LOCK LOCK~
這才是兩個主人並發訪問 就已經造成了這麼多等待,如果是100主人個並發調教,那得是多麼壯觀的隊伍!
我們的服務程式如果按照這個效率編寫 恐怕cpu佔用25%的時候就會崩潰---線程隊列的極限是多少? 按照Jeffery Richard 的話說 你提出這個問題的時候 就已經Very Very Wrong鳥。
換句話說,不要挑戰爺們的耐性,後果很嚴重
社會要進步 人民要革命 封建時代來臨
我們不能滿足這樣的效能。
老爺調教女奴的時候少爺不觀摩 這我們理解,(寫的時候加lock防止別的線程讀)
少爺和女僕喝茶的時候 老爺不能亂入開始餐廳調教,這我們也接受 (讀的時候加lock防止別的線程寫)
但是少爺們找女奴喝茶,沒有道理不可以一起開茶話會吧!
從某種意義上,只要集合元素不變化的話, Queue對象是支援安全的並發讀的,為什麼幾個線程都在讀取的狀況下,我們還要繼續上鎖彼此排斥對方呢? 我們只是純粹對女僕有愛,沒什麼不可以光明正大的吧!
把鎖從完全鎖變成讀寫鎖,能夠有效減少很多不需要的等待。—— 我們可以把喝茶的隊伍縮短!
Code Snippet
- class ChannelReadWriteLock
- {
- Queue<string> MessageQ = new Queue<string>();
- System.Threading.ReaderWriterLockSlim _lock = new System.Threading.ReaderWriterLockSlim();
- public void Say(string message) //寫資訊
- {
- _lock.EnterWriteLock();
-
- MessageQ.Enqueue(message);
- while (MessageQ.Count > 5) // 刪多餘
- {
- MessageQ.Dequeue();
- }
- _lock.ExitWriteLock ();
- }
- public string[] Listen() // \u-29701 ?所有
- {
- _lock.EnterReadLock ();
- var ary= MessageQ.ToArray();
- _lock.ExitReadLock();
- return ary;
- }
- \
這是女僕界的勝利 她不再是一個人(的人) 而是可以和人socal的普通人了 雖然還在封建家長制的陰影下,仍然是被剝削被蹂躪的底層民眾,但是她已經具有了比以前更大的自由!
先寫到這裡看看和諧底限 敬請期待 女僕編年史2