Java 中的锁(Locking)机制主要是为了解决多线程环境下,对共享资源并发访问时的同步和互斥控制,以确保共享资源的安全访问。
锁的作用主要体现在以下几个方面:
在 Java 中有很多锁策略,用于对锁进行分类和指导锁的(具体)实现,这些锁策略包括以下内容:
在 Java 中也有一些具体的锁实现,用于代码层面的锁操作以此来保证线程安全的,这些常见的锁实现有以下几个:
synchronized 可以用来修饰普通方法、静态方法和代码块。
public synchronized void method() { // .......}
当 synchronized 修饰普通方法时,被修饰的方法被称为同步方法,其作用范围是整个方法,作用的对象是调用这个方法的对象。
public static synchronized void staticMethod() { // .......}
当 synchronized 修饰静态的方法时,其作用的范围是整个方法,作用对象是调用这个类的所有对象。
为了减少锁的粒度,我们可以选择在一个方法中的某个部分使用 synchronized 来修饰(一段代码块),从而实现对一个方法中的部分代码进行加锁,实现代码如下:
public void classMethod() throws InterruptedException { // 前置代码... // 加锁代码 synchronized (SynchronizedExample.class) { // ...... } // 后置代码...}
以上代码在执行时,被修饰的代码块称为同步语句块,其作用范围是大括号“{}”括起来的代码块,作用的对象是调用这个代码块的对象。
ReentrantLock 基本使用:
// 1. 创建ReentrantLock对象ReentrantLock lock = new ReentrantLock();// 2.获取锁lock.lock(); try { // 3.得到锁,执行需要同步的代码块} finally { // 4.释放锁 lock.unlock(); }
进阶使用:尝试获取锁并设定超时时间(可选):
ReentrantLock lock = new ReentrantLock(); // 尝试获取锁,等待2秒,超时返回falseboolean locked = lock.tryLock(2, TimeUnit.SECONDS);if (locked) { try { // 执行需要同步的代码块 } finally { lock.unlock(); }}
ReentrantReadWriteLock 特点如下:
也就是说:读读不互斥、读写互斥、写写互斥。
ReentrantReadWriteLock 基础使用如下:
// 创建 ReentrantReadWriteLock 对象ReentrantReadWriteLock lock = new ReentrantReadWriteLock();// 创建读锁ReentrantReadWriteLock.ReadLock readLock = lock.readLock();// 获取读锁readLock.lock(); try { // 读取共享资源的操作} finally { // 释放读锁 readLock.unlock(); }// 创建写锁ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();// 获取写锁writeLock.lock();try { // 写入共享资源的操作} finally { // 释放写锁 writeLock.unlock(); }
StampedLock 有三种读写方法:
其中 readLock() 和 writeLock() 方法与 ReentrantReadWriteLock 的用法类似,而 tryOptimisticRead() 方法则是 StampedLock 引入的新方法,它用于非常短的读操作,它是使用如下:
// 创建 StampedLock 实例StampedLock lock = new StampedLock();// 获取乐观读锁long stamp = lock.tryOptimisticRead(); // 读取共享变量if (!lock.validate(stamp)) { // 检查乐观读锁是否有效 stamp = lock.readLock(); // 如果乐观读锁无效,则获取悲观读锁 try { // 重新读取共享变量 } finally { lock.unlockRead(stamp); // 释放悲观读锁 }}// 获取悲观读锁long stamp = lock.readLock(); try { // 读取共享变量} finally { lock.unlockRead(stamp); // 释放悲观读锁}// 获取写锁long stamp = lock.writeLock(); try { // 写入共享变量} finally { lock.unlockWrite(stamp); // 释放写锁}
使用乐观读锁的特性可以提高读操作的并发性能,适用于读多写少的场景。如果乐观读锁获取后,在读取共享变量前发生了写入操作,则 validate 方法会返回 false,此时需要转换为悲观读锁或写锁重新访问共享变量。
本文链接:http://www.28at.com/showinfo-26-88356-0.html字节面试:说说Java中的锁机制?
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 基于Spring Cloud Gateway,实现路由和负载均衡
下一篇: 14个 Python 自动化实战脚本