1、同步 I/O 和异步 I/O 的工作原理
1-1、同步 I/O 的细节
-
主动询问:在同步 I/O 中,CPU 会主动询问 I/O 控制器是否准备好了数据。
这个过程是通过多次的轮询实现的,CPU 发送请求后会持续检查状态,直到设备响应。
-
数据总线的占用:由于 CPU 不停地询问状态,它在等待 I/O 完成的过程中始终占用数据总线。
这不仅意味着它无法执行其他指令,也导致了资源的浪费。
-
阻塞状态:在这个过程中,CPU 处于阻塞状态,直到数据准备好为止。
这会影响整体性能,尤其在数据准备时间较长的情况下,CPU 的利用率会显著降低。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class SyncFileIO {
public static void main(String[] args) {
String filePath = "sync_example.txt";
// 写入文件
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
writer.write("This is a synchronous I/O example.\n");
writer.write("Data is written synchronously.");
} catch (IOException e) {
e.printStackTrace();
}
// 读取文件
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
1-2、异步 I/O 的细节
-
通知机制:在异步 I/O 中,CPU 发出请求后,不会等待 I/O 操作完成,而是可以继续执行其他指令。
I/O 控制器在内部准备数据,完成后通过中断来通知 CPU。
-
存储准备数据:I/O 控制器确实需要有一个缓冲区,用来存储数据,直到所有数据准备完毕。
这允许 I/O 操作在后台进行,而不影响 CPU 的其他计算。
-
状态保存:当中断信号到达时,CPU 会中断当前的执行状态,保存程序计数器、寄存器状态等,以便能够恢复执行。
此时,CPU 会使用数据总线与 I/O 控制器进行交互。
-
减少阻塞时间:虽然在中断处理阶段,CPU 仍然需要占用数据总线与 I/O 控制器交互,
但总体来看,CPU 在等待 I/O 完成的时间大幅减少,因为在这段时间它可以处理其他任务。
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
public class AsyncFileIO {
public static void main(String[] args) {
String filePath = "async_example.txt";
// 写入文件
CompletableFuture<Void> writeFuture = CompletableFuture.runAsync(() -> {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
writer.write("This is an asynchronous I/O example.\n");
writer.write("Data is written asynchronously.");
System.out.println("Writing completed.");
} catch (IOException e) {
e.printStackTrace();
}
});
// 读取文件
CompletableFuture<Void> readFuture = writeFuture.thenRunAsync(() -> {
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
System.out.println("Reading completed.");
} catch (IOException e) {
e.printStackTrace();
}
});
// 等待异步操作完成
readFuture.join();
}
}
2、本质区别
- 占用时间:同步 I/O 过程中,CPU 在整个请求期间都在占用数据总线,而异步 I/O 只在中断发生后进行短暂的数据交互,整体上 CPU 的阻塞时间显著降低。
- 设计思路:异步 I/O 的设计使得 CPU 和 I/O 设备的操作可以并行进行,提高了系统的效率。而同步 I/O 则是在每个请求完成前都需要等待,导致效率低下。