大神們來看看這樣架構 使用epoll有沒有問題?
01-08
前提:多線程,1個主線程,N個work線程
主線程主要是用來accept, 同時create N個epoll fd(注意在主線程中create)。然後把N個EPOLL FD 依次傳入N個work線程,每個線程對應唯一一個efd,
主線程中accept的sockfd隨機(或者輪詢...) 註冊到N個efd中的一個。在子線程中,運行事件循環,即epoll_wait(efd,....)這樣在主線程中的註冊的sockfd會在子線程中觸發。
這樣實現會有什麼問題么??這樣和平常的在每個線程中各自 create的epoll fd有什麼區別么?? 虛心求教---補充---之所以這樣做,是因為當初想,accept之後,主線程就對sockfd直接註冊到了對應的epoll fd中,而不用把sockfd放入到工作線程中的隊列中,等待工作線程去取出並註冊到efd。 這樣就省了一步。。。
陳碩說的這個問題,確實,這樣主線程還會執行epoll_ctl操作(只是ADD),而同時工作線程也會對同一efd執行epoll_ctl,epoll_wait操作,,這樣「對efd的跨線程並發操作。」 具體會帶來哪些問題呢??
問題不在於你主線程epoll_create而工作線程epoll_wait,
問題在於你的工作線程中epoll_wait的時候主線程去epoll_ctl,這是對efd的跨線程並發操作。
不是說這樣一定不行,而是為什麼你不把epoll_ctl也交給工作線程去處理呢?這樣肯定不會有問題。這樣沒問題,對epfd的操作無須另加互斥保護。但這樣的用意是什麼呢?其實epoll線程一個足夠了,epoll返回的事件分發到多個線程分別處理才是提高性能的關鍵。listenfd和普通傳入連接fd的epollin事件同樣處理即可,區別僅僅是一個調用accept一個調用read/recv
多線程還要考慮互斥,改成多進程也可以的
可以參考nginx的實現,多個進程(好像是CPU核數)同時監聽,誰搶到了就加入到自己的epoll中
每個工作線程創建的epoll實例,主線程只去做accept,這個操作可以用block方式,拿到的新連接fd分發到工作線程,接收到這個fd的worker線程,就可以在自己線程內做epoll_wait+epoll_ctl。不再需要主線的參與了。
建議去stackoverflow上問。。上面有類似問題的解答。。
既然用epoll, 那還搞這麼多線程幹嘛?
推薦閱讀:
※Linux 3.x 中epoll的驚群問題?
※node.js 底層使用的是epoll這種單線程io多路復用,還是多線程阻塞模型?