把文件发送到网卡,数据为什么要搬四次
一个静态文件已经保存在磁盘上,服务端只是把它原样发送给客户端。业务代码没有解析或修改文件内容,但如果使用普通的 read() 加 write(),数据仍会经过用户缓冲区,在内核与用户空间之间来回搬运。
DMA 让存储设备和网卡可以直接与内存交换数据,零拷贝则进一步减少 CPU 参与的内存复制。理解这两项技术,关键不是记住“几次拷贝、几次切换”的结论,而是沿着数据路径分清:哪一步由设备完成,哪一步由 CPU 完成,用户程序是否真的需要拿到文件内容。
一个静态文件已经保存在磁盘上,服务端只是把它原样发送给客户端。业务代码没有解析或修改文件内容,但如果使用普通的 read() 加 write(),数据仍会经过用户缓冲区,在内核与用户空间之间来回搬运。
DMA 让存储设备和网卡可以直接与内存交换数据,零拷贝则进一步减少 CPU 参与的内存复制。理解这两项技术,关键不是记住“几次拷贝、几次切换”的结论,而是沿着数据路径分清:哪一步由设备完成,哪一步由 CPU 完成,用户程序是否真的需要拿到文件内容。
Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配。同时,Java 自动内存管理最核心的功能是 堆 内存中对象的分配与回收。
Java 堆是垃圾收集器管理的主要区域,因此也被称作GC 堆(Garbage Collected Heap).从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代:再细致一点有:Eden 空间、From Survivor、To Survivor 空间等。进一步划分的目的是更好地回收内存,或者更快地分配内存。
Redis 分布式锁最危险的时刻,往往不是加锁失败,而是锁已经过期,旧的持有者却还在继续执行。
客户端 A 拿到一把有效期 10 秒的锁,业务执行中因为 GC、网络阻塞或外部接口超时停顿了 15 秒。租约到期后,客户端 B 成功加锁并开始工作。此时 A 恢复运行,两个客户端都会操作同一份资源。即使加锁和解锁命令写得完全正确,这个时间窗口仍然存在。
理解这一点以后,Redis 锁的安全边界才比较清楚:它可以协调并发,却不能独自保证共享资源永远只接受当前持有者的操作。