第 4 点我不怎么疑惑,毕竟书本说了,但是自旋会不会失去时间片呢,会不会也要用户态切换内核态呢,如果会的话自旋锁也逃避不了重量级锁的开销啊?
希望 v 站大佬可以指教一下小弟
1
MakHoCheung OP https://blog.51cto.com/u_15064655/2573032 这个已经解答了我的问题
|
2
tame619 2021-06-24 22:31:24 +08:00 via iPhone
自旋锁占用 cpu,只要系统分配到时间片,不超过次数就在自旋。超过了次数就升级。
|
3
MakHoCheung OP @tame619 自旋线程被调度就有开销了,所以自旋锁的情况下线程一般少于 cpu 的核数,这就是我看书说的竞争不激烈的情况下自旋锁有优势。你说的这是自旋锁怎么膨胀
|
4
tame619 2021-06-24 23:00:15 +08:00 via iPhone
@MakHoCheung 不是。线程上下文切换有开销,
如果一个同步块只要 0.01ms 解决,还不如牺牲 cpu 自旋。减少上下文切换 |
5
MakHoCheung OP @tame619 是啊,我刚刚说了“自旋线程被调度就有开销了”,我一开始不清楚这个,看了上面文章 这个就懂了,线程切换有开销
|
6
MakHoCheung OP @tame619 你说的这个也对
|
7
billlee 2021-06-25 01:16:55 +08:00
线程上下文切换指某个 CPU 核心从运行一个线程变为运行另一个线程,显然是需要进入内核态的
|
8
GeruzoniAnsasu 2021-06-25 08:19:29 +08:00 2
1. 线程是一个操作系统机制,不是语言机制。是“java 做了什么去适配线程机制”,而不是“java 怎么去实现线程机制”,这里的先后因果是不一样的。我发现其实有非常多人都不理解这个前提。
2. 先从单核多任务开始理解,显然任何语言的实现都无法提供一个强行从当前运行着的代码中断并跳到其它线程执行其它代码的非主动方法,所以这个切换一定是由硬件实现的(时钟中断)。所以这种线程切换必定要进入内核(用户态不处理硬件中断)。由于两个线程中的代码和变量都不一样,所以切过去时要保存 /恢复执行现场,所谓上下文 3. 当有两个线程共享一个资源并且要保证先后顺序的时候,自然而然的想法就是第一个线程把自己该干的活干完,然后主动告诉内核我干完了,让另一个线程继续干。这就是所谓的“等待”,本质上是主动交出执行权。 3. 进入多核时代,真并行任务开始变得普遍(以前也有多 CPU 架构,但基本与民用无关),从现在开始 CPU 可以同时执行多个线程,意味着切换上下文不再是必须的,多线程运行不一定会发生上下文切换。 4. 自旋锁解决的就是并行架构下两个线程各自执行时怎么保证数据一致的问题:让某一个线程自我循环等待另一个线程出结果。由于并行化,一个线程忙等也不会阻碍其它线程继续执行,所以在忙等效率比较高的情况下就让它忙等无妨,这是所谓自旋的“等待”,本质上是循环检查 5. 理解上述之后,给你一个要等待比如 1s 钟的锁,这么长时间对 cpu 来说显然是极大的浪费。所以虽然自旋也不影响其它线程,但还是让这个等待线程交出时间片先让其它线程来跑比较好,所以交出执行权还是循环检查这两种方式会看情况使用 现代多核 cpu 的多线程机制讲完了,再看你的问题基本都覆盖了 |
9
MakHoCheung OP @GeruzoniAnsasu 多谢,受教了
|