我在業餘時間開發維護了一款免費開源的升訊威線上客服系統,也收穫了許多使用者。對我來說,只要能獲得使用者的認可,就是我最大的動力。
最近客服系統成功經受住了客戶現場組織的壓力測試,獲得了客戶的認可。
客戶組織多名客服上線後,所有員工同一時間開啟訪客頁面瘋狂不停的給線上客服發訊息,系統穩定無異常無掉線,客服回覆訊息正常。訊息實時到達無任何延遲。
我會透過一系列的文章詳細分析升訊威線上客服系統的併發高效能技術是如何實現的,使用了哪些方案以及具體的做法。本文將介紹如何為多執行緒處理同步資料。
先看實現效果
客服端
訪客端
為多執行緒處理同步資料
多個執行緒可以呼叫單個物件的屬性和方法時,對這些呼叫進行同步處理是非常重要的。 否則,一個執行緒可能會中斷另一個執行緒正在執行的任務,可能使該物件處於無效狀態。 其成員不受這類中斷影響的類叫做執行緒安全類。
-
.NET 提供了幾種策略,用於同步對例項和靜態成員的訪問:
-
同步程式碼區域。 可以使用 Monitor 類或此類的編譯器支援,僅同步需要它的程式碼塊,從而提升效能。
-
手動同步。 可以使用 .NET 類庫提供的同步物件。 請參閱同步基元概述,其中介紹了 Monitor 類。
-
同步上下文。 僅對於 .NET Framework 和 Xamarin 應用程式,你可以使用 SynchronizationAttribute 為 ContextBoundObject 物件啟用簡單的自動同步。
-
System.Collections.Concurrent 名稱空間中的集合類。 這些類提供了內建的同步新增和刪除操作。 有關詳細資訊,請參閱執行緒安全集合。
公共語言執行時提供一個執行緒模型,在該模型中,類分為多種類別,這些類別可以根據要求以各種不同的方式進行同步。 下表顯示了為具有給定同步類別的欄位和方法提供的同步支援。
同步程式碼區域
可以使用 Monitor 類或編譯器關鍵字,同步程式碼塊、例項方法和靜態方法。 不支援同步靜態欄位。
Visual Basic 和 C# 都支援使用特定語言關鍵字標記程式碼塊,在 C# 中使用的是 lock 語句,在 Visual Basic 中使用的是 SyncLock 語句。 由執行緒執行程式碼時,會嘗試獲取鎖。 如果該鎖已由其他執行緒獲取,則在鎖變為可用狀態之前,該執行緒一直處於阻止狀態。 執行緒退出同步程式碼塊時,鎖會被釋放,與執行緒的退出方式無關。
由於 lock 和 SyncLock 語句是使用 Monitor.Enter 和 Monitor.Exit 實現,因此 Monitor 的其他方法可以在同步區域內與它們結合使用。
還可以使用值為 MethodImplOptions.Synchronized 的 MethodImplAttribute 修飾方法,其效果和使用 Monitor 或其中一個編譯器關鍵字鎖定整個方法正文相同。
Thread.Interrupt 可用於中斷對執行緒執行阻止操作(如等待訪問同步程式碼區域)。 Thread.Interrupt 還用於中斷對執行緒執行 Thread.Sleep 等操作。
Visual Basic 和 C# 均支援使用 Monitor.Enter 和 Monitor.Exit 鎖定物件的語言關鍵字。
在這兩種情況下,如果程式碼塊中引發異常,則 lock 或 SyncLock 獲取的鎖將自動釋放。 C# 和 Visual Basic 編譯器在發出 try/finally 塊時,在 try 的起始處使用 Monitor.Enter,在 finally 塊中使用 Monitor.Exit。 如果 lock 或 SyncLock 塊內部引發了異常,則會執行 finally 處理程式,從而允許執行任何清除工作。
WaitHandle 類和輕量同步型別
多個 .NET 同步基元派生自 System.Threading.WaitHandle 類,該類會封裝本機作業系統同步控制程式碼並將訊號機制用於執行緒互動。 這些類包括:
-
System.Threading.Mutex,授予對共享資源的獨佔訪問許可權。 如果沒有任何執行緒擁有它,則 mutex 將處於已發出訊號狀態。
-
System.Threading.Semaphore,限制可同時訪問某一共享資源或資源池的執行緒數。 當訊號量計數大於零時,會將訊號量的狀態設定為已發出訊號;當訊號量計數為零時,會將訊號量的狀態設定為未發出訊號。
-
System.Threading.EventWaitHandle,表示執行緒同步事件,可以處於已發出訊號狀態或未發出訊號狀態。
-
System.Threading.AutoResetEvent,派生自 EventWaitHandle,當發出訊號時,會在釋出單個等待執行緒後自動重置為未發出訊號狀態。
-
System.Threading.ManualResetEvent,派生自 EventWaitHandle,當發出訊號時,會保持已發出訊號狀態,直到呼叫 Reset 方法。
在 .NET Framework 中,由於 WaitHandle 派生自 System.MarshalByRefObject,因此,這些型別可用於跨應用程式域邊界同步執行緒的活動。
輕量同步型別不依賴於基礎作業系統控制程式碼,通常會提供更好的效能。 但是,它們不能用於程式間同步。 將這些型別用於一個應用程式中的執行緒同步。
其中的一些型別是派生自 WaitHandle 的型別的替代項。 例如,SemaphoreSlim 是 Semaphore 的輕量替代項。
同步對共享資源的訪問
System.Threading.Monitor 類透過獲取或釋放用於標識資源的物件上的 lock 來授予對共享資源的相互獨佔訪問許可權。 持有 lock 時,持有 lock 的執行緒可以再次獲取並釋放 lock。 阻止任何其他執行緒獲取 lock,Monitor.Enter 方法等待釋放 lock。 Enter 方法可獲取釋放的 lock。 還可以使用 Monitor.TryEnter 方法指定執行緒嘗試獲取 lock 的持續時間。 由於 Monitor 類具有執行緒關聯,因此獲取了 lock 的執行緒必須透過呼叫 Monitor.Exit 方法來釋放 lock。
可以透過使用 Monitor.Wait、Monitor.Pulse 和 Monitor.PulseAll 方法來協呼叫於獲取同一物件上的 lock 的執行緒的互動。
System.Threading.Mutex 類(與 Monitor 類似),授予對共享資源的獨佔訪問許可權。 使用 Mutex.WaitOne 方法過載之一請求 mutex 的所有權。 Mutex(與 Monitor 類似)具有執行緒關聯,並且已獲取 mutex 的執行緒必須透過呼叫 Mutex.ReleaseMutex 方法來釋放它。
Mutex 類(與 Monitor 不同)可用於程式間同步。 為此,請使用命名 mutex,它在整個作業系統中都可見。 若要建立命名 mutex 例項,請使用指定了名稱的 Mutex 建構函式。 還可以呼叫 Mutex.OpenExisting 方法來開啟現有的命名系統 mutex。
簡介
升訊威線上客服與營銷系統是一款客服軟體,但更重要的是一款營銷利器。
- 可以追蹤正在訪問網站或使用 APP 的所有訪客,收集他們的瀏覽情況,使客服能夠主動出擊,施展話術,促進成單。
訪* 客端在 PC 支援所有新老瀏覽器。包括不支援 WebSocket 的 IE8 也能正常使用。 - 移動端支援所有手機瀏覽器、APP、各大平臺的公眾號對接。
- 支援訪客資訊互通,可傳輸訪客標識、名稱和其它任意資訊到客服系統。
- 具備一線專業技術水平,網路中斷,拔掉網線,手機飛航模式,不丟訊息。同類軟體可以按影片方式對比測試。
-
- bilibili 影片:https://www.bilibili.com/video/BV1pK4y1N7UP?t=22
希望能夠打造: 開放、開源、共享。努力打造 .net 社群的一款優秀開源產品。