java中的锁

143 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

java中的锁

锁的作用

在java中,多线程在获取资源的时候,如何保证资源获取的有序性和占用形,是通过锁来控制的。

锁的分类

  1. 按照设计思路分

    乐观锁:每次拿到数据时默认别人不会修改,在更新数据时,判断别人是否更新,判断版本号是否和当前版本号一致,然后进行加锁操作,常见的乐观锁的使用方式是数据库表中添加version字段,每次更新数据时判断版本是否一致,修改成功后在当前版本号加一

    悲观锁:每次拿到数据时默认有人会修改,所以在读取数据时会上锁,别人在上锁期间拿不到该条数据,直至锁释放才可以查询到本条数据

  2. 按照锁的性质分类

    1. 公平锁和非公平锁

      公平锁:指多个线程按照申请的顺序来获取锁

      非公平锁:指多个线程获取锁的顺序并不是按照申请顺序获得锁,有可能后申请的线程比先申请的线程优先获取锁

    2. 互斥锁和读写锁

      互斥锁:互斥锁表现在锁之间互相排斥,只能有一个存在。

      读写锁:读写锁在Java中的具体实现就是ReentrantReadWriteLock。

    3. 独享锁和共享锁

      独享锁:独享锁是指该锁一次只能被一个线程所持有

      共享锁:共享锁是指该锁可被多个线程所持有

    4. 可重入锁

      指同一个线程在方法外部获取到锁后,在方法里自动获取到锁。

  3. 按照设计分类

    1. 自旋锁和自适应自旋锁

      自旋锁指在尝试获取锁的线程没有获取到锁时不会立刻阻塞,而是采用循环的方式尝试获取锁。自旋锁的优点是能减少线程上下文的切换消耗,缺点是会占用CPU资源。

    2. 锁消除和锁粗化

      锁消除指虚拟机在及时编译运行时,在一些同步代码上如果检测到不可能存在共享数据的竞争,会把同步代码上的锁去除。锁消除主要通过逃逸分析。锁粗化指一系列连续的操作都对同一个对象加锁解锁,会把加锁的范围扩大到整个操作序列外部。

    3. 偏向锁、轻量级锁和重量级锁

      这三种都是指锁的状态,而且都是在synchronized上,这三种锁的状态也是通过对象头中的标识来表明的。偏向锁指一段同步代码一直被一个线程访问,那么该线程自动获取到锁。轻量级锁指当锁是偏向锁,但被另一个线程访问时,偏向锁会升级为轻量级锁,其他线程或通过自选尝试获取锁,不会阻塞。重量级锁指当锁是轻量级锁后,另一个线程自旋后仍然没有获取到锁,就会进入阻塞,膨胀为重量级锁。

Java中常见的锁

Synchronized是一个:非公平,悲观,独享,互斥,可重入的重量级锁 Lock的实现包括:ReentrantLock和ReentrantReadWriteLock下的ReadLock和writeLock. ReentrantLock是一个:默认非公平但可实现公平的,悲观,独享,互斥,可重入,重量级锁。 ReentrantReadWriteLocK是一个,默认非公平但可实现公平的,悲观,写独享,读共享,读写,可重入,重量级锁。 CountDownLatch:CountDownLatch底层也是由AQS,用来同步一个或多个任务的常用并发工具类,强制它们等待由其他任务执行的一组操作完成