V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
MakHoCheung
V2EX  ›  问与答

关于 Java 线程的疑惑

  •  
  •   MakHoCheung · 2021-06-24 20:30:31 +08:00 · 1074 次点击
    这是一个创建于 589 天前的主题,其中的信息可能已经有所发展或是发生改变。
    1. 什么是线程上下文切换呢,指的是就绪状态(没分到时间片)转到运行状态(分到时间片)或者调转过来这样子吗
    2. 线程切换需要用户态切换到内核态吗
    3. 自旋锁情况下,抢占的线程自旋过程是一直在运行状态吗(分到时间片)
    4. 我看书说到线程竞争重量级锁时候抢占不成功就从 Runnable (就绪或者运行状态)状态转阻塞状态,此时需要用户态切换到内核态来转状态,这时候就会有开销

    第 4 点我不怎么疑惑,毕竟书本说了,但是自旋会不会失去时间片呢,会不会也要用户态切换内核态呢,如果会的话自旋锁也逃避不了重量级锁的开销啊?

    希望 v 站大佬可以指教一下小弟

    9 条回复    2021-06-25 09:00:13 +08:00
    MakHoCheung
        1
    MakHoCheung  
    OP
       2021-06-24 21:44:25 +08:00
    https://blog.51cto.com/u_15064655/2573032 这个已经解答了我的问题
    tame619
        2
    tame619  
       2021-06-24 22:31:24 +08:00 via iPhone
    自旋锁占用 cpu,只要系统分配到时间片,不超过次数就在自旋。超过了次数就升级。
    MakHoCheung
        3
    MakHoCheung  
    OP
       2021-06-24 22:48:10 +08:00
    @tame619 自旋线程被调度就有开销了,所以自旋锁的情况下线程一般少于 cpu 的核数,这就是我看书说的竞争不激烈的情况下自旋锁有优势。你说的这是自旋锁怎么膨胀
    tame619
        4
    tame619  
       2021-06-24 23:00:15 +08:00 via iPhone
    @MakHoCheung 不是。线程上下文切换有开销,
    如果一个同步块只要 0.01ms 解决,还不如牺牲 cpu 自旋。减少上下文切换
    MakHoCheung
        5
    MakHoCheung  
    OP
       2021-06-24 23:07:13 +08:00
    @tame619 是啊,我刚刚说了“自旋线程被调度就有开销了”,我一开始不清楚这个,看了上面文章 这个就懂了,线程切换有开销
    MakHoCheung
        6
    MakHoCheung  
    OP
       2021-06-24 23:08:21 +08:00
    @tame619 你说的这个也对
    billlee
        7
    billlee  
       2021-06-25 01:16:55 +08:00
    线程上下文切换指某个 CPU 核心从运行一个线程变为运行另一个线程,显然是需要进入内核态的
    GeruzoniAnsasu
        8
    GeruzoniAnsasu  
       2021-06-25 08:19:29 +08:00   ❤️ 2
    1. 线程是一个操作系统机制,不是语言机制。是“java 做了什么去适配线程机制”,而不是“java 怎么去实现线程机制”,这里的先后因果是不一样的。我发现其实有非常多人都不理解这个前提。

    2. 先从单核多任务开始理解,显然任何语言的实现都无法提供一个强行从当前运行着的代码中断并跳到其它线程执行其它代码的非主动方法,所以这个切换一定是由硬件实现的(时钟中断)。所以这种线程切换必定要进入内核(用户态不处理硬件中断)。由于两个线程中的代码和变量都不一样,所以切过去时要保存 /恢复执行现场,所谓上下文
    3. 当有两个线程共享一个资源并且要保证先后顺序的时候,自然而然的想法就是第一个线程把自己该干的活干完,然后主动告诉内核我干完了,让另一个线程继续干。这就是所谓的“等待”,本质上是主动交出执行权。

    3. 进入多核时代,真并行任务开始变得普遍(以前也有多 CPU 架构,但基本与民用无关),从现在开始 CPU 可以同时执行多个线程,意味着切换上下文不再是必须的,多线程运行不一定会发生上下文切换。
    4. 自旋锁解决的就是并行架构下两个线程各自执行时怎么保证数据一致的问题:让某一个线程自我循环等待另一个线程出结果。由于并行化,一个线程忙等也不会阻碍其它线程继续执行,所以在忙等效率比较高的情况下就让它忙等无妨,这是所谓自旋的“等待”,本质上是循环检查

    5. 理解上述之后,给你一个要等待比如 1s 钟的锁,这么长时间对 cpu 来说显然是极大的浪费。所以虽然自旋也不影响其它线程,但还是让这个等待线程交出时间片先让其它线程来跑比较好,所以交出执行权还是循环检查这两种方式会看情况使用



    现代多核 cpu 的多线程机制讲完了,再看你的问题基本都覆盖了
    MakHoCheung
        9
    MakHoCheung  
    OP
       2021-06-25 09:00:13 +08:00
    @GeruzoniAnsasu 多谢,受教了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   1589 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 09:23 · PVG 17:23 · LAX 01:23 · JFK 04:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.