前言
之前也做过不少的分布式、多线程系统,对线程同步异步的理解还是不到位,现归纳总结一下。
多线程
多线程并发程序通过同时执行多个任务来提高 CPU 利用率,线程通过共享对象引用和成员变量相互通信。
当多个线程共享同一内存(资源)时,多个对同一数据执行不同操作的线程可能会相互交错,并在内存中创建不一致的数据,产生线程干扰错误。
使线程安全的办法有许多,如:
- 同步
- 施加多个线程对同一对象的访问限制
- 将变量声明为final
- 将变量声明为volatile
- 创建不可变对象
- 等等
也就是说,在多线程的场景中,同步是维护线程安全的一种方式。这篇文章可以学习借鉴一下。
同步、异步
同步(synchronized):A线程要请求某资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程阻塞,等待资源可用再进行。
异步(asynchronized):A线程要请求某资源,但是此资源正在被B线程使用中,因为没有同步机制存在,A线程可以请求得到此资源,无需等待。
同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。
异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作。而异步方法通常会在另外一个线程中“真实”地执行着。整个过程,不会阻碍调用者的工作(即不阻碍当前进程)。最终通过状态来通知调用者,或通过回调函数来处理执行结果。
同步显然是安全的,但使系统性能降低;异步速度快,但可能导致死锁,引发更大安全问题。
阻塞与同步
同步与异步和阻塞机制不能混为一谈,虽然通常有所关联。
同步和异步强调的是消息通信机制,而 阻塞和非阻塞 强调的是程序在等待调用结果(消息,返回值)时的状态。
阻塞时,在调用结果返回前,当前线程会被挂起,并在得到结果之后返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
对于同步调用来说,很多时候当前线程还是激活的状态,只是从逻辑上当前函数没有返回而已,即同步等待时什么都不干,白白占用着资源。
举例说说
同步
Tomcat,通过自建的线程池实现同步阻塞式IO模型。详细见这篇文章
异步
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型。Node.js是单线程的,利用异步IO和事件驱动(回调函数)来解决高并发的问题。详细可以看看这篇文章。
后记
随想随写写,后续再完善吧,有很多值得深挖的点。