java锁的理解

java锁

1.概念

Java锁(Java Locks)是Java编程语言中用于实现多线程同步和互斥的机制。在并发编程中,多线程同时访问共享资源可能导致竞态条件(Race Condition)和其他并发问题,Java锁提供了一种控制多线程并发访问的方式,以确保线程安全(Thread Safety)和正确的数据访问。如Synchronized关键字、ReentrantLock类、Read/Write Locks等
线程开发遇到的安全问题分为三个维度:原子性、可见性、有序性。在多线程开发过程中,Synchronized可以解决绝大多数的线程安全问题,多数时候选择不同的锁是为了提高代码的性能。
例如:当两个线程,同时给一个为0的变量进行++操作时,可能会出现两种结果:1或者2,原因是++操作是非原子性的。在底层逻辑中,这个步骤会分为三步,首先获取参数值,然后进行+1操作,然后写入内存,在线程1获取到变量值的时候线程2可能会同时获取变量值,也可能其中一个先获取到参数加一并写入内存操作后,另一个再获取参数进行加一操作。因此这种情况下,就需要加锁(同步锁)来进行处理。

2.锁的类别

从功能层面:

共享锁(读锁):在同一时刻允许多个线程抢占到锁
排它锁(写锁):在同一时刻只允许一个线程抢占到锁

从性能层面:

1.锁粒度优化:锁范围缩小
2.无锁编程
乐观锁:cas->原子性/可见性,通过数据的版本来去控制多线程并发的安全性,不需要去竞争锁
悲观锁:强制加锁机制,认为所有访问都要加锁访问
3.偏向锁/轻量级锁/重量级锁 -->(目的:减少锁的竞争)

  • 自旋锁(轻量级锁):阻塞等待之前去重试竞争锁,避免了阻塞与唤醒(轻微竞争
  • 偏向锁:针对防御性编程,当线程1进入锁时,当前不存在竞争,会将锁偏向于线程1,则下次线程1再进入锁时,就不再需要去竞争锁,减少竞争(没有竞争
  • 重量级锁:加锁的实现方式,即进行锁的竞争后执行指令(存在竞争

4.锁消除/锁膨胀:java编译器层面的优化
锁消除:当加入锁时,但此处不存在锁竞争,则编译器会自动忽略该锁
锁膨胀:当锁控制的粒度太小,导致频繁竞争时,编译器会自动膨胀锁的粒度,减少竞争
5.读写锁读多写少的情况下):读和读不去竞争,但读和写、写和写去进行竞争锁。
6.公平锁/非公平锁
大部分锁的设计都是非公平锁,因为非公平锁减少了锁的等待,减少了线程的阻塞和唤醒。

从锁的特性层面:

1.重入锁(防死锁设计):当一个线程抢占到锁,在释放锁之前再次去竞争同一把锁的时候,不需要阻塞等待,直接进入重试次数,java中大部分的锁都是可重入的。
2.分布式锁:解决java分布式下的进程维度的锁的粒度问题。

3.锁的本质

竞争锁的机制:设置一个同步状态->state=0,当其中一个线程进入锁后,将状态修改为1,则其他线程进入锁时进行判断state是否等于1即可。Synchronized去实现同步状态是通过Mutex机制来实现互斥状态的处理,而Mutex机制是内核层面,因此锁的过程涉及到用户态到内核态的切换,用户线程阻塞等待,切换到内核线程来运行,同时还要保存当前线程执行的上下文(线程的阻塞唤醒以及上下文的保存),会消耗部分性能。
总结: 对性能影响的体现:

  • 竞争同步状态时,涉及到上下文的切换
  • 线程的阻塞与唤醒,也会涉及到上下文的切换
  • 从并行到串行的改变

4.锁的优化

竞争同步状态时无法进行优化,这是一个必然的过程;从并行到串行的改变也无法进行优化,这是加锁后的作用;线程的阻塞与唤醒过程可以优化,防止线程阻塞与唤醒过程,即防止切换线程,可以引入自旋锁的概念。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值