阻塞等於同步,非阻塞等於非同步這種說法有什麼錯誤?

分不太清楚阻塞和同步,非阻塞和非同步的區別。
現在處於一種好像懂了,但是應該是沒懂的情況。
我的理解一直在
阻塞:卡著不動,要等到完成返回=同步:卡著不動,要等到執行完返回 都是順序執行
非阻塞:等價於系統開個線程幫你執行,完了告不告訴你看你有沒有設通知=非同步 都是系統幫你像開個線程一樣並行執行


"同步非同步"和"阻塞非阻塞"是兩個不同範圍的概念。

synchronous / asynchronous is to describe the relation between two modules.
blocking / non-blocking is to describe the situation of one module.

An example:
"I": a
"bookstore" : b

a asks b: do you have a book named "c++ primer"?

1) blocking: before b answers a, a keeps waiting there for the answer. Now a (one module) is blocking. a and b are two threads or two processes or one thread or one process? we DON"T know.
2) non-blocking: before b answers a, a just leaves there and every two minutes, a comes here for looking for the answer. Here a (one module) is non-blocking. a and b are two threads or two processes or one process? we DON"T know. BUT we are sure that a and b couldn"t be one thread.

3) synchronous: before b answers a, a keeps waiting there for the answer. It means that a can"t continue until b finishes its job. Now we say: a and b (two modules) is synchronous. a and b are two threads or two processes or one thread or one process? we DON"T know.

4) asynchronous: before b answers a, a leaves there and a can do other jobs. When b gets the answer, b will call a: hey! I have it! Then a will come to b to get the book when a is free. Now we say: a and b (two modules) is asynchronous. a and b are two threads or two processes or one process? we DON"T know. BUT we are sure that a and b couldn"t be one thread.

所以,阻塞可以是非同步的(a阻塞了但a和b是非同步的);非阻塞也可以是同步的(a非阻塞但a和b是同步的)。

非阻塞同步例子:

bool getReply = false;
string msg;
a.listenAndAccept(b);
while(!getReply)
{
if(a.recv(b, FLAG_NONBLOCKING) &> 0) // a got the reply from b
{
msg = b.reply();
getReply = true;
continue;
}
sleep(1); // 1 sec
}
// do something with msg

在這個例子中,每當執行a.recv時,a就去看一下有沒有b的回復,如果沒有,a不會block在這裡,而是會立刻往下走---sleep 1秒,然後循環。什麼時候a得到b的回復了,則循環結束,然後a就可以拿著b的回復去做相應的工作了。

也就是說,a是非阻塞的,但是a和b的關係是同步關係---因為a必須等b給它回復了,它才能拿這個回復去做一些事情。


在實際情況中,上面的這種非阻塞同步的用處不大,應該說一般不會用到。因為a不阻塞,會一直佔用CPU,但是其實它只是很sb地一次次地去看b有沒有回復(這也就是為什麼在那裡要sleep一下,否則會造成CPU資源嚴重浪費)。因此在實際中,我們一般會讓a多線程:一條線程阻塞等待b的回復,其他線程做其他不需要b回復的工作;與此同時b工作並在工作結束後給a回復---這就是阻塞非同步:即,a是阻塞的而a和b是非同步的。

就我能想到的非阻塞的用途:

a和b玩遊戲,a出題b答題。要求答題時間不能超過1分鐘。此時你就可以這樣:

a.PoseAQuestionTo(b);
a.sleep(60); // 60 sec
if(a.recv(b, FLAG_NONBLOCKING) &<= 0) { a.SendMsg(b, "you lose!"); } /* * 注意:這裡雖然沒有把recv放在一個循環里,但這並不意味著要求a必須恰好在1分鐘的時刻點上 * 給出答案。b在30秒時發送答案,你在60秒時去listen也可以拿到的,因為socket監聽的端 * 口有一定的緩存空間。當然,如果在b的答案非常大以至於一個緩存空間都放不下,那麼就需要循環 * 以實現多次接受然後最終合成一個信息---所以通常情況下,socket的recv都應該在一個循 * 環里,不論是不是阻塞。 */

如果上述內容都看懂了,你自己很容易就可以舉出阻塞同步、非阻塞非同步的例子。


阻塞與同步,非阻塞與非同步是完全不相關的概念。首先你要記住這一點。
你的困惑也是可以理解的,阻塞和同步在表現上確實很像,阻塞看起來確實是卡著不動,同步也是的。但阻塞其實不叫卡,因為它是調用了某個系統調用,而這個系統調用讓它的調用線程睡眠了,此時是不佔cpu的。但是,實現同步的方式除了阻塞之外,非阻塞也能實現。比如你弄一個while循環一直等一個標誌位置位。
非阻塞跟非同步的概念也是完全不同的,你完全可以使用非阻塞的系統調用,然後輪巡等待就緒。


簡單理解就是,阻塞是指做任務的時候你得等著,非阻塞是指做任務的時候你可以自己去干別的;同步是指任務完沒完成你得自己去查,非同步是指任務完成了會觸發回調函數通知你。


你餓了么叫外賣。
點完菜乾等著啥也不幹,在門口等菜來了你自己取菜吃。---阻塞、同步
點完菜在家看電視、畫畫、看書,在門口等菜來了你自己取菜吃。---非阻塞、同步
點完菜乾等著啥也不幹,等快遞打你電話你出門收菜吃。---阻塞、非同步
點完菜在家看電視、畫畫、看書,等快遞打你電話你出門收菜吃。---非阻塞、非同步


題主的問題沒有說得很明白呀,是不是多線程之間的阻塞同步?


推薦閱讀:

2台路由器不同網段如何互訪?
你對未來會成為程序員的在校學習學生有什麼話可以說?
計算機專業,如何選擇電腦?
賣電腦配件的都是奸商么?
這個文件夾怎麼刪掉?

TAG:編程 | 計算機 | C編程語言 | Socket | 網路編程 |