GeruzoniAnsasu
2021-06-25 08:19:29 +08:00
1. 线程是一个操作系统机制,不是语言机制。是“java 做了什么去适配线程机制”,而不是“java 怎么去实现线程机制”,这里的先后因果是不一样的。我发现其实有非常多人都不理解这个前提。
2. 先从单核多任务开始理解,显然任何语言的实现都无法提供一个强行从当前运行着的代码中断并跳到其它线程执行其它代码的非主动方法,所以这个切换一定是由硬件实现的(时钟中断)。所以这种线程切换必定要进入内核(用户态不处理硬件中断)。由于两个线程中的代码和变量都不一样,所以切过去时要保存 /恢复执行现场,所谓上下文
3. 当有两个线程共享一个资源并且要保证先后顺序的时候,自然而然的想法就是第一个线程把自己该干的活干完,然后主动告诉内核我干完了,让另一个线程继续干。这就是所谓的“等待”,本质上是主动交出执行权。
3. 进入多核时代,真并行任务开始变得普遍(以前也有多 CPU 架构,但基本与民用无关),从现在开始 CPU 可以同时执行多个线程,意味着切换上下文不再是必须的,多线程运行不一定会发生上下文切换。
4. 自旋锁解决的就是并行架构下两个线程各自执行时怎么保证数据一致的问题:让某一个线程自我循环等待另一个线程出结果。由于并行化,一个线程忙等也不会阻碍其它线程继续执行,所以在忙等效率比较高的情况下就让它忙等无妨,这是所谓自旋的“等待”,本质上是循环检查
5. 理解上述之后,给你一个要等待比如 1s 钟的锁,这么长时间对 cpu 来说显然是极大的浪费。所以虽然自旋也不影响其它线程,但还是让这个等待线程交出时间片先让其它线程来跑比较好,所以交出执行权还是循环检查这两种方式会看情况使用
现代多核 cpu 的多线程机制讲完了,再看你的问题基本都覆盖了