1. 程式人生 > >epoll的多執行緒安全性問題

epoll的多執行緒安全性問題

  最近在嘗試模仿muduo網路庫封裝自己的mini網路庫,陳碩老師推薦使用one loop per thread + 非阻塞IO的程式設計模型。於是準備採用一個主事件迴圈專門讀取處理新的連線,而用數個(根據CPU核心數確定)從執行緒處理各個連線的業務的方式來實現新的伺服器,這裡就牽涉到一個問題,如果讀取連線的主執行緒向從執行緒新增新的監聽事件的時候會不會存線上程安全性的問題?epoll_ctl是執行緒安全的,但是若從執行緒正因epoll_wait阻塞的話,結果如何呢?
  
最權威的參考當然是Linux自帶的man手冊,原文如下:
  While one thread is blocked in a call to epoll_pwait(), it is possible for another thread to add a file descriptor to the waited-upon epoll instance. If the new file descriptor becomes ready, it will cause the epoll_wait() call to unblock.
For a discussion of what may happen if a file descriptor in an epoll instance being monitored by epoll_wait() is closed in another thread, see select(2)
  大意是,當一個執行緒阻塞在epoll_wait()上的時候,其他執行緒向其中新增新的檔案描述符是沒問題的,如果這個檔案描述符就緒的話,阻塞執行緒的epoll_wait()會被喚醒。但是如果正在監聽的某檔案描述符被其他執行緒關閉的話詳情見select。查閱select原文如下
  If a file descriptor being monitored by select() is closed in another thread, the result is unspecified. On some UNIX systems, select() unblocks and returns, with an indication that the file descriptor is ready (a subsequent I/O operation will likely fail with an error, unless another the file descriptor reopened between the time select() returned and the I/O operations was performed). On Linux (and some other systems), closing the file descriptor in another thread has no effect on select(). In summary, any application that relies on a particular behavior in this scenario must be considered buggy
  大意是,若一個檔案描述符正被監聽,其他執行緒關閉了的話,表現是未定義的。在有些 UNIX系統下,select會解除阻塞返回,而檔案描述符會被認為就緒,然而對這個檔案描述符進行IO操作會失敗(除非這個檔案描述符又被分配了),在Linux下,另一個執行緒關閉檔案描述符沒有任何影響。但不管怎樣,這樣做都是2B行為,應當儘量壁面一個執行緒關閉另一個執行緒在監聽的檔案描述符。