最近在看Java多線程部分,提到了很多同步的問題,又想起《計算機(jī)系統(tǒng)概論》中輸入輸出章節(jié)講到的同步I/O和異步I/O,所以這里總結(jié)一些有關(guān)同步和異步以及阻塞和非阻塞的一些思考。
同步和異步
同步和異步的關(guān)注點在于被調(diào)用者是如何把返回值(或者說是信息)傳回給調(diào)用者的
如果說被調(diào)用者直接把信息返回,這樣調(diào)用者就必須等待返回值,這是同步。
如果說被調(diào)用者是通過另外一些方法(如回調(diào))把信息傳遞給調(diào)用者,這樣調(diào)用者可以不需要等待返回值回來,而繼續(xù)執(zhí)行,那么這就是異步。
阻塞和非阻塞
阻塞和非阻塞的關(guān)注點在于調(diào)用者獲得這個返回值的時候的狀態(tài)是怎樣的。
如果在等待這個返回值,那么是阻塞的,如果沒有在等待這個返回值,那么是非阻塞的。
Talk is cheep,show me the code --- Linux
- 同步阻塞:
int i = in.nextInt();
//這里是同步的,因為nextInt()是直接將返回值返回的。
//這里也是阻塞的,因為這里的 i 一直在等待nextInt()的返回值,如果在線程中,這個線程會被掛起
- 同步非阻塞:
while(true)
{
if(in.hasNext())
{
int i = in.nextInt();
//nextInt() 是同步的,nextInt()是直接把值返回的
//nextInt()是非阻塞的,程序并沒有一直等待值返回,而是do somethig,并在必要的時候check一下是否完成了。
//簡單的講,同步非阻塞就是**輪詢**。
break;
}
//do something
}
- 異步阻塞:
class Caller
{
private int flag;
public void setFlag(int flag)
{
this.flag = flag;
}
public static void main(String[] args)
{
flag=0;
BeCaller.doSomething(this);
//doSomething()不是將信息直接返回的,而是使用回調(diào)的方式,所以是異步的
while(a==0)
;
//由于while循環(huán),所以信息返回時,調(diào)用者是一直在等待的,所以他是阻塞的。
//do Something
}
}
class BeCaller
{
public static void doSomething(Caller callback)
{
//do something
callback.setFlag(1);
}
}
- 異步非阻塞
class Caller
{
public void Callback(int flag)
{
System.out.println(flag);
//信息返回時,調(diào)用者并沒有在等待,所以他是非阻塞的。
}
public static void main(String[] args)
{
flag=0;
BeCaller.doSomething(this);
//doSomething()不是將信息直接返回的,而是使用回調(diào)的方式,所以是異步的
//do Something
}
}
class BeCaller
{
public static void doSomething(Caller callback)
{
//do something
callback.Callback(1);
}
}
- 同步阻塞可以類比成你去某家很火的餐廳吃飯,因為太火爆了,餐廳暫時沒有位置,服務(wù)員讓你排號,拿到號碼后,你就在餐廳門口的什么都不干的傻等。
- 同步非阻塞就是你拿到號碼后再餐廳附近轉(zhuǎn)轉(zhuǎn)干些別的事情,然后時不時的回去看看到你了沒
-
異步非阻塞就是你留了一個號碼給服務(wù)員,讓服務(wù)員到你的時候打給你。
-異步阻塞就是你已經(jīng)叫了服務(wù)員到你的時候打給你,一直在門口傻等,一直問到你了沒。(所以這個一般沒什么用)
總結(jié)一下
- 同步還是異步,看返回值是如何返回的。
- 阻塞還是非阻塞,看返回時,調(diào)用者有沒有在等。