2010-01-27 1389 views
4

在Linux中,如果創建兩個線程並且它們都在運行,當其中一個線程調用recv()或任何IO系統調用在沒有可用數據時會阻塞時,整個過程會發生什麼?當一個線程被阻塞時,其他線程會發生什麼?

另一個線程會阻塞嗎?我想這取決於線程是如何實現的。如果線程庫在用戶空間和內核完全不知道進程內的線程,那麼進程就是調度實體,因此兩個線程都被阻塞。

此外,如果其他線程沒有因爲這個的塊,它可以然後通過相同的插座,其被阻塞recv線程send()數據?雙面打印?

任何想法?

回答

1

如果線程在內核空間或用戶空間中實現,則絕對正確,阻塞行爲取決於該線程。如果線程純粹是在用戶空間中實現的(也就是說,內核完全不受線程影響),那麼任何進入內核的阻止入口點都需要封裝一些非阻塞變體,可以將阻塞語義模擬爲其調用的「線程「(例如使用AIO發送/接收數據而不是阻塞,並且完成回調使得線程可以再次運行)。

在Linux(和所有其他現存的主要操作系統,我能想到的),穿線在內核級別執行,或相似,並且阻塞調用進入內核將事業的所有其他線程阻塞。

是的,您可以將send()添加到另一個線程在recv()上被阻止的套接字。

+0

謝謝!一個相當完整的答案。好決定。 – Figo 2010-01-27 22:23:18

+0

還有一個問題,如果在線程調用recv()之前有數據到達套接字,線程是否會真正獲取這些數據? – Figo 2010-01-27 22:36:35

+0

是的。這是它在非阻塞數據報套接字上工作的唯一方式。一些小小的筆記,我打算有所幫助 - 其中一個,你可以很容易地嘗試這種事情。編寫一個小程序來「接受」連接,然後「休眠」一段時間,然後在新連接上調用「recv」。使用'nc'(netcat)或其他來創建與服務器的連接,並立即向其中寫入一些數據。您會看到服務器獲得了與您發送的數據相同的數據。第二個說明 - 這實際上是關於什麼是通常是一次性問題論壇的第三個不同的問題...... – 2010-01-27 22:55:39

2

在一個線程中阻塞調用不應該影響其他線程。

如果被阻塞的線程在進入阻塞調用之前鎖定了互斥鎖,並且第二個線程試圖鎖定同一個互斥鎖,那麼他們第二個線程需要等待阻塞調用完成並釋放第一個線程鎖。

+0

謝謝,然後它下降到第二個問題:其他非阻塞線程可以通過同一個套接字發送()數據,而recv()阻塞另一個?假設UDP。 – Figo 2010-01-27 22:13:19

2

完全可以在用戶空間中實現線程,以便一個線程可以繼續執行,而另一個線程在I/O上阻塞。

非阻塞的線程應該能夠在套接字上發送,而另一個線程阻塞它(我寫了這樣的代碼)。

+0

謝謝,這是個好消息。 – Figo 2010-01-27 22:15:10

+0

只有當系統調用支持所有的非阻塞調用時纔有可能。很有可能會在fstat之類的所有用戶線程上停頓幾秒鐘。 – 2010-01-27 22:22:26

+0

@贊恩Lynx:他正在談論Linux,它具有POSIX-complient aio_read()和aio_write()系統調用。 – 2010-01-28 20:07:50

相關問題