【Java零基础】Java核心知识点之:JAVA锁(上)

【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】

**开源地址:https://docs.qq.com/doc/DSmxTbFJ1cmN1R2dB **

  • JDK 1.6 中默认是开启偏向锁和轻量级锁,可以通过-XX:-UseBiasedLocking 来禁用偏向锁。

5.ReentrantLock

ReentantLock 继承接口 Lock 并实现了接口中定义的方法,他是一种可重入锁,除了能完成 synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等避免多线程死锁的方法。

Lock 接口的主要方法

  • void lock(): 执行此方法时, 如果锁处于空闲状态, 当前线程将获取到锁. 相反, 如果锁已经被其他线程持有, 将禁用当前线程, 直到当前线程获取到锁.

  • boolean tryLock():如果锁可用, 则获取锁, 并立即返回 true, 否则返回 false. 该方法和lock()的区别在于, tryLock()只是"试图"获取锁, 如果锁不可用, 不会导致当前线程被禁用,当前线程仍然继续往下执行代码. 而 lock()方法则是一定要获取到锁, 如果锁不可用, 就一直等待, 在未获得锁之前,当前线程并不继续向下执行.

  • void unlock():执行此方法时, 当前线程将释放持有的锁. 锁只能由持有者释放, 如果线程并不持有锁, 却执行该方法, 可能导致异常的发生.

  • Condition newCondition():条件对象,获取等待通知组件。该组件和当前的锁绑定,当前线程只有获取了锁,才能调用该组件的 await()方法,而调用后,当前线程将缩放锁。

  • getHoldCount() :查询当前线程保持此锁的次数,也就是执行此线程执行 lock 方法的次数。

  • getQueueLength():返回正等待获取此锁的线程估计数,比如启动 10 个线程,1 个线程获得锁,此时返回的是 9getWaitQueueLength:(Condition condition)返回等待与此锁相关的给定条件的线程估计数。比如 10 个线程,用同一个 condition 对象,并且此时这 10 个线程都执行了condition 对象的 await 方法,那么此时执行此方法返回 10

  • hasWaiters(Condition condition):查询是否有线程等待与此锁有关的给定条件(condition),对于指定 contidion 对象,有多少线程执行了 condition.await 方法

  • hasQueuedThread(Thread thread):查询给定线程是否等待获取此锁

  • hasQueuedThreads():是否有线程等待此锁

  • isFair():该锁是否公平锁

  • isHeldByCurrentThread(): 当前线程是否保持锁锁定,线程的执行 lock 方法的前后分别是 false 和 true

  • isLock():此锁是否有任意线程占用

  • lockInterruptibly():如果当前线程未被中断,获取锁

  • tryLock():尝试获得锁,仅在调用时锁未被线程占用,获得锁

  • tryLock(long timeout TimeUnit unit):如果锁在给定等待时间内没有被另一个线程保持,则获取该锁。

非公平锁

JVM 按随机、就近原则分配锁的机制则称为不公平锁,ReentrantLock 在构造函数中提供了是否公平锁的初始化方式,默认为非公平锁。非公平锁实际执行的效率要远远超出公平锁,除非程序有特殊需要,否则最常用非公平锁的分配机制。

公平锁

公平锁指的是锁的分配机制是公平的,通常先对锁提出获取请求的线程会先被分配到锁,ReentrantLock 在构造函数中提供了是否公平锁的初始化方式来定义公平锁。

ReentrantLock 与 synchronized

  • ReentrantLock 通过方法 lock()与 unlock()来进行加锁与解锁操作,与 synchronized 会被 JVM 自动解锁机制不同,ReentrantLock 加锁后需要手动进行解锁。为了避免程序出现异常而无法正常解锁的情况,使用 ReentrantLock 必须在 finally 控制块中进行解锁操作。

  • ReentrantLock 相比 synchronized 的优势是可中断、公平锁、多个锁。这种情况下需要使用ReentrantLock。

ReentrantLock 实现

public class MyService {

private Lock lock = new ReentrantLock();

//Lock lock=new ReentrantLock(true);//公平锁

//Lock lock=new ReentrantLock(false);//非公平锁

private Condition condition=lock.newCondition();//创建 Condition

public void testMethod() {

try {

lock.lock();//lock 加锁

//1:wait 方法等待:

//System.out.println(“开始 wait”);

condition.await();

//通过创建 Condition 对象来使线程 wait,必须先执行 lock.lock 方法获得锁

//:2:signal 方法唤醒

condition.signal();//condition 对象的 signal 方法可以唤醒 wait 线程

for (int i = 0; i < 5; i++) {

System.out.println(“ThreadName=” + Thread.currentThread().getName()+ (" " + (i + 1)));

}

} catch (InterruptedException e) {

e.printStackTrace();

}

finally

{

lock.unlock();

}

} }

Condition 类和 Object 类锁方法区别区别

  • Condition 类的 awiat 方法和 Object 类的 wait 方法等效

  • Condition 类的 signal 方法和 Object 类的 notify 方法等效

  • Condition 类的 signalAll 方法和 Object 类的 notifyAll 方法等效

  • ReentrantLock 类可以唤醒指定条件的线程,而 object 的唤醒是随机的

tryLock 和 lock 和 lockInterruptibly 的区别

  • tryLock 能获得锁就返回 true,不能就立即返回 false,tryLock(long timeout,TimeUnitunit),可以增加时间限制,如果超过该时间段还没获得锁,返回 false

  • lock 能获得锁就返回 true,不能的话一直等待获得锁

  • lock 和 lockInterruptibly,如果两个线程分别执行这两个方法,但此时中断这两个线程,lock 不会抛出异常,而 lockInterruptibly 会抛出异常。

6. Semaphore 信号量

Semaphore 是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信 号,做完自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore 可以用来 构建一些对象池,资源池之类的,比如数据库连接池。

实现互斥锁(计数器为 1)

我们也可以创建计数为 1 的 Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。

代码实现

它的用法如下:

// 创建一个计数阈值为 5 的信号量对象

// 只能 5 个线程同时访问

Semaphore semp = new Semaphore(5);

try { // 申请许可

semp.acquire();

try {

// 业务逻辑

} catch (Exception e) {

} finally {

// 释放许可

semp.release();

}

} catch (InterruptedException e) {

}

Semaphore 与 ReentrantLock

Semaphore 基本能完成 ReentrantLock 的所有工作,使用方法也与之类似,通过 acquire()与release()方法来获得和释放临界资源。经实测,Semaphone.acquire()方法默认为可响应中断锁,与ReentrantLock.lockInterruptibly()作用效果一致,也就是说在等待临界资源的过程中可以被Thread.interrupt()方法中断。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值