最近在看Java多线程部分,提到了很多同步的问题,又想起《计算机系统概论》中输入输出章节讲到的同步I/O和异步I/O,所以这里总结一些有关同步和异步以及阻塞和非阻塞的一些思考。
同步和异步
同步和异步的关注点在于被调用者是如何把返回值(或者说是信息)传回给调用者的
如果说被调用者直接把信息返回,这样调用者就必须等待返回值,这是同步。
如果说被调用者是通过另外一些方法(如回调)把信息传递给调用者,这样调用者可以不需要等待返回值回来,而继续执行,那么这就是异步。
阻塞和非阻塞
阻塞和非阻塞的关注点在于调用者获得这个返回值的时候的状态是怎样的。
如果在等待这个返回值,那么是阻塞的,如果没有在等待这个返回值,那么是非阻塞的。
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()不是将信息直接返回的,而是使用回调的方式,所以是异步的
while(a==0)
;
//由于while循环,所以信息返回时,调用者是一直在等待的,所以他是阻塞的。
//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);
//信息返回时,调用者并没有在等待,所以他是非阻塞的。
}
public static void main(String[] args)
{
flag=0;
BeCaller.doSomething(this);
//doSomething()不是将信息直接返回的,而是使用回调的方式,所以是异步的
//do Something
}
}
class BeCaller
{
public static void doSomething(Caller callback)
{
//do something
callback.Callback(1);
}
}
- 同步阻塞可以类比成你去某家很火的餐厅吃饭,因为太火爆了,餐厅暂时没有位置,服务员让你排号,拿到号码后,你就在餐厅门口的什么都不干的傻等。
- 同步非阻塞就是你拿到号码后再餐厅附近转转干些别的事情,然后时不时的回去看看到你了没
-
异步非阻塞就是你留了一个号码给服务员,让服务员到你的时候打给你。
-异步阻塞就是你已经叫了服务员到你的时候打给你,一直在门口傻等,一直问到你了没。(所以这个一般没什么用)
总结一下
- 同步还是异步,看返回值是如何返回的。
- 阻塞还是非阻塞,看返回时,调用者有没有在等。