pursue wind pursue wind
首页
Java
Python
数据库
框架
Linux
中间件
前端
计算机基础
DevOps
项目
面试
书
关于
归档
MacOS🤣 (opens new window)
GitHub (opens new window)
首页
Java
Python
数据库
框架
Linux
中间件
前端
计算机基础
DevOps
项目
面试
书
关于
归档
MacOS🤣 (opens new window)
GitHub (opens new window)
  • 技术面试题篇

  • 面试准备篇

  • 技术面试题自测篇

  • 练级攻略篇

  • 工作篇

  • 面经篇

  • 笑傲Java面试

    • 2-1 导学-Java编程技巧部分
    • 2-2 IDEA Java配置补充
    • 2-4 Java8 Stream 接口:流和并发计算实例
    • 2-5 和面试官聊聊实现管道和流计算的基石:函数式的Monad
    • 2-6 Buffer的原理和使用场景+面试题解读
    • 2-7 补充提问:同步和阻塞、异步和非阻塞等不等价?
      • [](#实战演示示例程序,具体见视频)实战演示(示例程序,具体见视频)
      • [](#总结)总结
    • 2-8 阿里面试题:中文乱码处理和大文件计算词频
    • 2-9 实战场景Coding训练:解读反射+代理+AOP 并结合业务逻辑实现
    • 2-10 注解部分答案
    • 2-11 反射-元编程面试题目合集
    • 2-12 面试必备:Java8-11的新特性和理解的误区
    • 2-13 白板篇-Java编程总结(以及面试题)
    • 3-1 算法和数据结构导学
    • 3-2 教你面试时不会忘记的5种手写排序
    • 3-3 手写链表算法
    • 3-4 手写栈和队列面试专项
    • 3-5 课后习题+面试题:用栈和队列实现表达式解析
    • 3-6 迷宫伪代码和8皇后问题源代码
    • 3-7 3-7 树部分源代码
    • 3-8 8皇后问题
    • 3-10 动态规划的课前题目
    • 3-11 总结和课后习题:白板篇-数据结构和算法
    • 4-1 解读:并发编程知识体系
    • 4-2 看看你的基础:Java线程状态之间如何转换?
    • 4-3 CAS和原子操作
    • 4-4 同步器(上篇)——面试官问synchronized本质是什么?
    • 4-5 同步器(中)——AbstractQueuedSynchronizer
    • 4-6 面试官:说6个Java的同步器?
    • 4-7 面试官出难题:并发环境下单例怎么写性能最高
    • 4-8 面试官:LinkedBlockingDeque和SynchronousQueue工作原理一样吗?
    • 4-9 面试要点:volatile的简短补充
    • 4-10 给面试官讲讲无锁编程(Lock-Free Programming)
    • 4-11 高阶并发编程Coding训练:N种优化哲学家就餐问题的方法
    • 4-12 并发基础篇:总结和思考题
    • 4-13 并发部分的通关Boss: 生成、发放大量红包并控制资金流速
  • LeetCode

  • 面试
  • 笑傲Java面试
pursuewind
2021-12-13
目录

2-7 补充提问:同步和阻塞、异步和非阻塞等不等价?

# 补充提问:同步和阻塞、异步和非阻塞等不等价?

经常听人说,异步的请求会马上返回。同步的请求会阻塞,比如下面这段程序,因为read方法马上返回,所以就是异步方法。

var result = read((data) -> {
  System.out.println(data);
});

System.out.println(result); // 数据没准备好

这种说法对嘛?

我们说同步和异步,实际上是一种程序结构的差异。同步的程序要求程序之间是一种顺序的因果关系。

程序之间的因果是上文和下文之间的关系。上面的read方法是“因”, 这个“因”影响范围,应该是Read下面的程序,而不是read的参数中的程序。

所以上面这个程序的设计并不好,因为因果关系发生了问题。我们不希望把我们的程序不要复杂化。那就是有因就有果,因果之间是顺序的。比如这样:

var result = read();
System.out.println(result); // 数据OK 

你可以对比下这两种写法你更喜欢哪种?当然是现在这种对我们的心智负担最小。这一种写法叫做同步(synchronous),在同步的程序中,因果的关系紧密连接。这样,程序员的心智负担低。上面看到那种带回调函数的方式叫做异步(asynchronous)。在异步的方法中,因果关系不是顺序的,程序员的心智负担高,容易犯错。

var t = new Thread(() -> {
    // 位置1
});

// 位置2
t.interrupt();

比如上面这段程序,就是一个异步的程序。那么位置2和位置1谁先执行呢?完全不能控制。所以我们在做程序设计的时候,我们经常要把需要异步的程序转变成同步的程序。创建线程的的程序是一个特例,异步可能是唯一合理的方案。

接下来这段程序使用了NIO的AsynchronousFileChannel去读取文件。

    @Test
    public void test_async_read() throws IOException, ExecutionException, InterruptedException {

        var fileName = "word";
        var channel = AsynchronousFileChannel.open(Path.of(fileName), StandardOpenOption.READ);

        var buf = ByteBuffer.allocate(1024);
        Future<Integer> operation = channel.read(buf, 0);
        var numReads = operation.get();
        buf.flip();
        var chars = new String(buf.slice().array());
        System.out.println(chars);
    }

你可以仔细观察一下这段程序。Future价值。在于它将一个本该异步的。数据读取过程。转化成了同步的逻辑。关于Future,我们会在并发编程章节中继续讨论。channel.read(buf, 0)不会阻塞,代码会阻塞在operation.get 。有了这样的关系。你可以在任何位置去执行operation.get。所以channel.read(buf, 0)是非阻塞同步。operation.get是阻塞同步。

同步是好事,同步意味着程序好写的。

阻塞(Blocking)意味着实实在在发生了线程阻塞的行为。阻塞操作会导致当前线程阻塞:当前线程发生了中断,切换到其他线程去执行。阻塞可不可以异步呢?当然可以,比如这段程序:

sleep(1000ms, () -> {
  
});

假设上面这段程序,会发生阻塞(交出控制权),直到1s的时候中断触发回调,才会继续执行回调函数。那么这就是一个异步阻塞的程序。

非阻塞(Non-Blocking)说的是线程的行为没有发生阻塞,就叫非阻塞。比如:

int num = read(fd, buf);
if(num == 0) {
    // 没有读取到数据
}

假设上面这段程序中,read函数总是马上返回,就是非阻塞。因此这就是一段,同步非阻塞的程序。

# 实战演示(示例程序,具体见视频)

# 总结

同步、异步说的是程序的写法。阻塞、非阻塞说的是线程的行为。

Last Updated: 2023/01/30, 11:01:00
2-6 Buffer的原理和使用场景+面试题解读
2-8 阿里面试题:中文乱码处理和大文件计算词频

← 2-6 Buffer的原理和使用场景+面试题解读 2-8 阿里面试题:中文乱码处理和大文件计算词频→

Theme by Vdoing | Copyright © 2019-2023 pursue-wind | 粤ICP备2022093130号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
  • 飙升榜
  • 新歌榜
  • 云音乐民谣榜
  • 美国Billboard榜
  • UK排行榜周榜
  • 网络DJ