Java中的‘锁’- synchronized、ReentrantLock、ReentrantReadWriteLock

简介: 1、隐式锁 对称线程同步 synchronized    用法:1、在方法声明时使用;2、修饰代码块中使用    隐式规则        1、当两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,一个时间内...

1、隐式锁 对称线程同步 synchronized

    用法:1、在方法声明时使用;2、修饰代码块中使用

    隐式规则

        1、当两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行

        2、当一个线程访问object的一个synchronized(this)同步代码块时,其他的线程可以访问该object中的非synchronized(this)同步代码块

        3、synchronized(this)设置的对象锁中,当一个线程访问获取到锁,其他线程对object中相同对象锁的代码块都无法访问

    性能和执行效率:

        同步方法体<同步代码块 <synchronized(this)<同步代码块(byte锁)

    如图1-2

img_2a2dd86debe67f11e941690c595f072d.png
图1-2

    关于效率高低的判断,其实记住一点,锁时一个对象,加锁和释放锁都需要资源,对象越小效率越高 

2、显式锁Lock和ReentrantLock

Lock只是一个接口,它规定了锁的基础操作规范

如图2-1所示

img_b7ed491f5407908f54392958517116ef.png
图2-1

        1、Lock()方法,线程获取锁,如果锁不可用,则禁用当前线程,在获得锁之前,该线程一直处于休眠

        2、unlock()方法,释放锁,一般情况下,每个获取的锁都要对应一个释放锁

img_dea55c21808622a33690e9e1ce9b0cfc.png

    其他的方法像是lockInterruptibly、tryLock、tryLock(long time, TimeUnit unit)这几个方法无非就是在获取锁的过程中判断了一些条件,这里需要注意的是,方法中的锁一定要是共有的,如果是独立的锁,那么起不到相应的作用

3、显示锁,读写锁ReadWriteLock和ReentrantReadWriteLock

        ReadWriteLock是一个接口,只有两个方法,readLock()和writeLock(),此处注意,ReadWriteLock并不是Lock的子接口,但是ReadWriteLock中的读写锁都是依靠Lock来进行实现的

读写锁的机制:

    1、读读不互斥:多线程读,并发不堵塞

    2、读写互斥:有线程在写,那么所有的读线程就会堵塞,反过来,有读的线程在使用,写线程就会堵塞

    3、写写互斥:写线程都是互斥的,两个线程去写,谁先拿到锁,就先写

img_c7c31fe441a193782126c657da0b1285.png
图3-1

图3-1中是同时使用读写锁的时候的业务场景,比较经典的缓存场景

img_73d2a5821fc1f120f15148635996c0d9.png
图3-2
img_c83094bd51f551882fc3390daa8e10dd.png
图3-3

图3-2和图3-3则是模拟高并发的情况下的读写锁单独使用的情况下,图3-2的是模拟高并发的单元测试代码,图3-3是读写锁的代码

读写锁和普通锁的区别,

    1、相同点:其实都是一种显式锁,手动加锁和解锁,都比较适合高并发场景

    2、不同点:ReentrantReadWriteLock是对ReentrantLock的一种扩展,ReentrantReadWriteLock适合更加复杂的业务场景,可以实现一个方法的读写分离

相关文章
|
28天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
28天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
55 3
|
2月前
|
缓存 Java
java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁
本文介绍了几种常见的锁机制,包括公平锁与非公平锁、可重入锁与不可重入锁、自旋锁以及读写锁和互斥锁。公平锁按申请顺序分配锁,而非公平锁允许插队。可重入锁允许线程多次获取同一锁,避免死锁。自旋锁通过循环尝试获取锁,减少上下文切换开销。读写锁区分读锁和写锁,提高并发性能。文章还提供了相关代码示例,帮助理解这些锁的实现和使用场景。
java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁
|
2月前
|
Java 开发者
Java 中的锁是什么意思,有哪些分类?
在Java多线程编程中,锁用于控制多个线程对共享资源的访问,确保数据一致性和正确性。本文探讨锁的概念、作用及分类,包括乐观锁与悲观锁、自旋锁与适应性自旋锁、公平锁与非公平锁、可重入锁和读写锁,同时提供使用锁时的注意事项,帮助开发者提高程序性能和稳定性。
120 3
|
2月前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
52 4
|
3月前
|
Java
Java 中锁的主要类型
【10月更文挑战第10天】
|
Java
java源码 - ReentrantLock之FairSync
开篇  这篇文章主要是讲解FairSync公平锁的源码分析,整个内容分为加锁过程、解锁过程,CLH队列等概念。  首先一直困扰我的CLH队列的CLH的缩写我终于明白,看似三个人的人名的首字符缩写"CLH" (Craig, Landin, andHagersten)。
1038 0
|
Java
java源码 - ReentrantLock之NonfairSync
开篇  NonfairSync和FairSync相比而言,多了一次抢占机会,其他处理逻辑几乎是一模一样。 NonfairSync的tryAcquire的操作流程中如果发现当前锁未被占用那么立即抢占锁。
1090 0
|
15天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
72 17
|
26天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者