Chormium執行緒模型及應用指南
核心概念
設計上遵循以下原則:
1 不要在UI執行緒做任何阻塞式的I/O操作,以及其它耗時的操作,通過訊息傳遞把各種操作傳給相應用途的執行緒去做。
2 不鼓勵執行緒加鎖機制和執行緒安全物件。物件只存在一個執行緒,通過訊息來實現執行緒之間的通訊,執行緒之間不互相阻塞。通過callback物件實現跨執行緒請求。
一般情況下,我們應該利用一個現有的執行緒,儘量不要建立新的執行緒。UI執行緒實際上會被設定為不允許I/O操作,並且不允許等待。
執行緒列表
核心執行緒列表
所屬程式 | 執行緒名稱 | 型別 | 職責 | 實現 |
---|---|---|---|---|
Browser | UI / BrowserThread | Java | Browser的主執行緒 | content::BrowserThreadImpl |
Browser | Chrome_DBThread | Native | 負責資料庫(SQLite)相關的操作,很多功能的實現會用到該執行緒。 | content::BrowserThreadImpl |
Browser | Chrome_FileThread | Native | 檔案的建立、刪除、讀寫等。 | content::BrowserThreadImpl |
Browser | Chrome_FileUserBlockingThread | Native | 用於讀取與使用者互動有關的資料,需要快速的響應。看到net log模組和appcache有用。 | content::BrowserThreadImpl |
Browser | Chrome_ProcessLauncherThread | Native | 用於啟動和終止子程式。 | content::BrowserThreadImpl |
Browser | Chrome_CacheThread | Native | ||
content::BrowserThreadImpl | ||||
Browser | IndexedDB | Native | IndexDB儲存執行緒。 | base::Thread |
GPU | Chrome_InProcGpuThread | Native | GPU的單程式版本實現。 | content::InProcessGpuThread |
Child Processes | Chrome_ChildIOThread | Native | 子程式的IO執行緒實現。 | base::Thread |
Renderer | Chrome_InProcRendererThread | Native | Renderer程式的單程式版本實現。 | content::InProcessRendererThread |
其它執行緒
執行緒名稱 | Module | 實現 | 說明 |
---|---|---|---|
CookieMonsterClient | CAW | base::Thread | |
CookieMonsterBackend | CAW | base::Thread | |
CookieSyncManager | WebView | Runnable | |
Chrome_libJingle_WorkerThread | Browser | base::Thread | |
Blink Heap Marker Thread (*) | Blink | base::Thread | |
Blink GC Sweeper (*) | Blink | base::Thread | |
HTMLParserThread | Blink | base::Thread | |
AsyncTransferThread | gpu | gpu::TransferThread | |
BrowserBlocking Worker | Browser | base::SequencedWorkerPool | 詳見:Chromium中應用C/C++併發技術要點 |
SimpleCache Worker | net | base::SequencedWorkerPool | |
Network File Thread | net | base::Thread |
執行緒結構
(以單程式模型說明)
Android下執行緒的訊息結構
Chromium的執行緒結構
各個類的職責說明:
類 | 職責說明 |
---|---|
RunLoop | 一個輔助類,主要封裝訊息迴圈 MessageLoop 類,其本 |
MessageLoop | 主訊息迴圈,原理上講,它應該可以處理三種型別的訊息,包括支援不同平臺的訊息。 事實上,如果讓它處理所有這些訊息,這會讓其程式碼結構複雜不清難以理解。訊息迴圈只需要三種型別:
對於第二和第三種 MessageLoop 型別,它們除了要處理任務外,還要處理平臺相關的訊息,為了結構清晰, |
MessagePump | 一個抽象出來的基類,可以用來處理上面所列的第二和第三種訊息型別。對於每個平臺,它們有不同的 |
摘自:<<理解WebKit和Chromium>>
Browser端執行緒結構
Browser端拋轉執行緒訊息,主要是基於BrowserThread提供的方法來完成的,如下:
// 檢測所在的執行緒 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); // 拋轉任務到UI執行緒執行 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&AwLoginDelegate::HandleHttpAuthRequestOnUIThread, this , (count->auth_attempts_ == 0 ))); // 拋轉任務到IO執行緒 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(&AwLoginDelegate::ProceedOnIOThread, this , user, password)); |
Render端的執行緒結構
Renderer端拋轉訊息,主要是基於MessageLoopProxy來完成。如下:
base::Closure closure = base::Bind(&CompositorOutputSurface::ShortcutSwapAck, weak_ptrs_.GetWeakPtr(), output_surface_id_, base::Passed(&frame->gl_frame_data), base::Passed(&frame->software_frame_data)); base::MessageLoopProxy::current()->PostTask(FROM_HERE, closure); // input_event_filter.cc中的示例 io_loop_->PostTask(FROM_HERE, base::Bind(&InputEventFilter::SendMessageOnIOThread, this , base::Passed(&message))); // Blink platform implemetation base::MessageLoopProxy::current()->PostTask( FROM_HERE, base::Bind(&PlatformEventObserverBase::SendFakeDataForTesting, base::Unretained(observer), data)); |
gpu與Browser/Renderer的互動
執行緒安全
對於Java及Android的執行緒安全不再展開,可以參考附件的資料:<<Efficient Android Threading Asynchronous Processing Techniques for Android Applications>>
關於Java則推薦《Java併發實戰》。
最常用的形式,將使用的物件定義為base::RefCountedThreadSafe。保證引用的物件不會被提前析構。
對於一些非執行緒安全的類可以使用NonThreadSafe提供Debug模式下執行緒安全確認。也可以應用ThreadCollisionWarner/ThreadChecker 確保執行執行緒與設計一致。
參考: 如何安全的使用PostTask
任務的取消
除了任務按需要取消外,如果在宿主類析構後執行就可能導致崩潰。目前使用兩種方式保證任務的取消:
WeakPtrFactory (WeakPtr)和CancelableTaskTracker, 它們析構時也會自動將任務取消。
CancelableTaskTracker可以參考Chromium官網的說明或是在FaviconCache中的應用。
class UserInputHandler : public base::RefCountedThreadSafe<UserInputHandler> { // Runs on UI thread. void OnUserInput(Input input) { CancelPreviousTask(); DBResult* result = new DBResult(); task_id_ = tracker_->PostTaskAndReply( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(), FROM_HERE, base::Bind(&LookupHistoryOnDBThread, this , input, result), base::Bind(&ShowHistoryOnUIThread, this , base::Owned(result))); } void CancelPreviousTask() { tracker_->TryCancel(task_id_); } ... private : CancelableTaskTracker tracker_; // Cancels all pending tasks while destruction. CancelableTaskTracker::TaskId task_id_; ... }; |
對於WeakPtr,Chromium已經封裝了一個WeakptrFactory供使用。可以參考GpuBrowserCompositorOutputSurface中的使用。使用方式比較簡單,但沒有CancelableTaskTracker通用。
下面是一個簡單的示例(使用WeakPtrFactory<>最大的好處是不用修改類的定義.)
class MyObject { public : MyObject() : weak_factory_( this ) {} void DoSomething() { const int kDelayMS = 100 ; MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind(&MyObject::DoSomethingLater, weak_factory_.GetWeakPtr()), kDelayMS); } void DoSomethingLater() { ... } private : base::WeakPtrFactory<MyObject> weak_factory_; }; |
*非執行緒安全,可以跨執行緒傳遞,但必須在一個執行緒上使用這個WeakPtr,即只能在執行在相同執行緒的任務上使用這個機制。
*類中WeakPtrFactory<Foo> weak_factory_的成員需要放在所有其他成員的後面,確保其他成員的解構函式執行的時候WeakPtrs還是無效的。
關於WeakPtr的進一步解釋可以參考: Chromium中的weak_ptr,以及 關於SupportWeakPtr與WeakPtrFactory的選擇.
相關文章
- Reactor執行緒模型及其在Netty中的應用React執行緒模型Netty
- 多執行緒應用執行緒
- 執行緒模型執行緒模型
- 執行緒建立的函式及應用小結執行緒函式
- 常用高併發網路執行緒模型設計及mongodb執行緒模型優化實踐執行緒模型MongoDB優化
- Dubbo執行緒模型執行緒模型
- WPF執行緒模型執行緒模型
- redis執行緒模型Redis執行緒模型
- osi7層模型及執行緒和程式模型執行緒
- 執行緒池的實現原始碼及應用舉例執行緒原始碼
- Dubbo的執行緒模型執行緒模型
- 程式和執行緒模型執行緒模型
- Redis的執行緒模型Redis執行緒模型
- 03.執行緒模型執行緒模型
- webrtc執行緒模型分析Web執行緒模型
- ObjC 多執行緒簡析(一)-多執行緒簡述和執行緒鎖的基本應用OBJ執行緒
- Spring Boot執行緒安全指南Spring Boot執行緒
- 可本地執行大模型的應用大模型
- PyQt應用程式中的多執行緒:使用Qt還是Python執行緒?QT執行緒Python
- 多執行緒之共享模型執行緒模型
- 小度分享-【多執行緒工作及執行緒安全】執行緒
- 多執行緒之間通訊及執行緒池執行緒
- 玩轉java多執行緒 之多執行緒基礎 執行緒狀態 及執行緒停止實戰Java執行緒
- 執行緒池執行模型原始碼全解析執行緒模型原始碼
- 多執行緒應用初探(一)----(概念,安全)執行緒
- mongodb核心原始碼實現及效能最佳化:常用高併發執行緒模型設計及mongodb執行緒模型最佳化實踐MongoDB原始碼執行緒模型
- 多執行緒的執行緒狀態及相關操作執行緒
- 簡述CUDA執行緒及求CUDA中執行緒索引執行緒索引
- Netty原始碼解析一——執行緒池模型之執行緒池NioEventLoopGroupNetty原始碼執行緒模型OOP
- 淺談Netty的執行緒模型Netty執行緒模型
- Java 執行緒記憶體模型Java執行緒記憶體模型
- (三)Redis 執行緒與IO模型Redis執行緒模型
- Redis之單執行緒 Reactor 模型Redis執行緒React模型
- Redis執行緒模型的前世今生Redis執行緒模型
- 詳談執行緒池的理解和應用執行緒
- 編寫執行緒安全的JSP應用程式執行緒JS
- Python 多執行緒及程式Python執行緒
- Node.js 的單執行緒事件驅動模型和內建的執行緒池模型Node.js執行緒事件模型
- javascript執行緒及與執行緒有關的效能優化JavaScript執行緒優化