V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
shangzhanyu
V2EX  ›  Java

Java 轻量级锁使用在无竞争场景,那么为什么还要用它?

  •  
  •   shangzhanyu · 2020-11-30 17:54:11 +08:00 · 3564 次点击
    这是一个创建于 1433 天前的主题,其中的信息可能已经有所发展或是发生改变。

    无竞争场景不用锁不就可以了?为什么要多此一举呢?

    第 1 条附言  ·  2020-12-02 13:47:21 +08:00

    花了一天时间按照层次整理了一下锁相关的内容

    • Java:java.util.concurrent包、synchroized
    • jvm:重入锁、cas、自适应锁、偏向锁 -> 轻量级锁 -> 重量级锁
    • 操作系统:互斥量、信号量、原子性、自旋锁、大内核锁、RCU、读/写锁
    • 硬件:
      • 单核cpu:原子性指令和指令集、总线锁、缓存锁
      • 多核cpu:缓存一致性协议MESI
    22 条回复    2020-12-01 20:34:55 +08:00
    Jooooooooo
        1
    Jooooooooo  
       2020-11-30 17:55:36 +08:00
    你完全理解错了

    无竞争是事后才知道的
    shangzhanyu
        2
    shangzhanyu  
    OP
       2020-11-30 18:00:27 +08:00
    @Jooooooooo 怎么讲?
    ApachW
        3
    ApachW  
       2020-11-30 18:11:07 +08:00
    应该是开始没并发,线程一个执行完了过了会才来一个,这时候是轻量锁,然后程序跑着跑着并发来了,锁就升级了
    liuch
        4
    liuch  
       2020-11-30 18:21:49 +08:00
    使用锁的目的是为了保证竞争下面的数据安全,这个是大前提。
    但是在某些场景下,竞争可能不存在或者不激烈。这种情况下,使用重量级锁性能不佳,也没有必要
    轻量级锁 是优化处理这种情况。后面可能会有的 线程的竞争,就会有锁升级的情况发生。
    shangzhanyu
        5
    shangzhanyu  
    OP
       2020-11-30 18:31:29 +08:00
    @ApachW 那直接使用互斥锁不是更好吗
    hdbzsgm
        6
    hdbzsgm  
       2020-11-30 18:34:39 +08:00
    @shangzhanyu 开销 /性能
    wuketidai
        7
    wuketidai  
       2020-11-30 18:53:31 +08:00
    乐观锁?
    SuperManNoPain
        8
    SuperManNoPain  
       2020-11-30 19:02:58 +08:00
    不用切换到内核态,maybe
    kkkkkrua
        9
    kkkkkrua  
       2020-11-30 19:17:47 +08:00
    你加了锁之后,这个锁是肯定存在的,这是前提
    然后是,存在后,因为没竞争,所以此时的锁是偏向 /轻量锁
    后面才是有竞争后,会锁升级。
    不知道这么讲你理解不
    kkkkkrua
        10
    kkkkkrua  
       2020-11-30 19:20:22 +08:00
    @kkkkkrua #9 当然,反过来讲,经过逃逸分析后,会锁消除的
    nicoley
        11
    nicoley  
       2020-11-30 20:23:11 +08:00
    @shangzhanyu 直呼好家伙!你用互斥锁考虑过系统整体的并发吗?
    jtchris
        12
    jtchris  
       2020-11-30 20:44:53 +08:00   ❤️ 1
    偏向锁没法在应用中吧(至少我不会...),是 JVM 为了优化性能搞得。你加了锁,但是程序实际运行中发现,就一个线程访问,并没有其它线程来竞争,为了提高性能就不搞同步那些了。
    比如你去饭馆买饭,收银员给你发了号码,服务员叫号上菜,当就你一个顾客时,服务员就没叫号直接给你端上来了,省了他叫号和你回答的步骤,提高了上菜速度。
    JsonTu
        13
    JsonTu  
       2020-11-30 23:01:20 +08:00 via iPhone
    @jtchris 这个比喻到位
    goodboy95
        14
    goodboy95  
       2020-12-01 09:10:27 +08:00
    轻量级锁对于 1 个线程来说确实等于没有锁啊,人家自旋的是第二个线程
    nicoley
        15
    nicoley  
       2020-12-01 09:54:44 +08:00
    在实际场景中,你不可以预测后面有没有线程来抢夺资源吧,如果后面随着线程竞争加剧还会出现锁升级等等。所以用轻量级锁的目的就是防微杜渐。
    securityCoding
        16
    securityCoding  
       2020-12-01 10:08:38 +08:00
    一楼说的狠明白 ,一开始你怎么知道有没有狗子跟你抢东西吃呢
    shangzhanyu
        17
    shangzhanyu  
    OP
       2020-12-01 10:09:32 +08:00
    @nicoley 这么解释能理解了,为了防止可能出现的竞争场景,一般在什么场景下使用?
    shangzhanyu
        18
    shangzhanyu  
    OP
       2020-12-01 10:10:46 +08:00
    @securityCoding 比如什么场景呢?
    securityCoding
        19
    securityCoding  
       2020-12-01 10:21:32 +08:00
    @shangzhanyu 当锁是偏向锁的时候,被另外的线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。
    securityCoding
        20
    securityCoding  
       2020-12-01 10:23:43 +08:00
    @shangzhanyu 抱歉看错了。
    偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价。
    在大多数情况下,锁总是由同一线程多次获得,不存在多线程竞争,所以出现了偏向锁。其目标就是在只有一个线程执行同步代码块时能够提高性能。

    从这篇文章( https://tech.meituan.com/2018/11/15/java-lock.html )看来的,美团的技术文章写的都挺不错的。
    shangzhanyu
        21
    shangzhanyu  
    OP
       2020-12-01 13:09:58 +08:00
    @jtchris 意思是这些是 jvm 对锁的优化,应用中没有对应的使用方式是吗?
    jtchris
        22
    jtchris  
       2020-12-01 20:34:55 +08:00
    @shangzhanyu 这是 JVM 源码的实现,JDK 是没有这类 API 的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2805 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:34 · PVG 22:34 · LAX 07:34 · JFK 10:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.