AQS基础
文章目录
前言
本文就介绍一下AQS基础可重入锁synchronized 以及ReentrantLock
提示:以下是本篇文章正文内容,下面案例可供参考
一、synchronized and ReentrantLock?
<font color=#999AAA 我们首先来介绍一下synchronized可重入锁(递归锁)
二、简单理解synchronized
1.synchronized 引入 代码块
1.可重入锁(又名递归锁)
有一个锁的抢占 有一个锁的释放
在某种 情况下 这个程序不止有一层
指同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提,锁对象是同一个对象(同步锁))
在java 里面 reentrantlock 和 synchronized 都是可重入锁,可重入锁有一个优点是可一定程度避免 死锁
Synchronized 关键字 隐式锁 默认是可重入锁
显式锁 Lock 锁 也有 ReentrantLock这样的 可重入锁
代码如下(示例)在同步代码块:
private static void m1() {
new Thread(()->{
synchronized (o){
System.out.println(Thread.currentThread().getName()+"外层");
synchronized (o){
System.out.println(Thread.currentThread().getName()+"中层");
synchronized (o){
System.out.println(Thread.currentThread().getName()+"内层");
}
}
}
},"q1").start();
}
2.效果如下
代码如下(示例):
q1外层
q1中层
q1内层
1.synchronized 修饰的方法
代码如下(示例)在同步方法:
public class Test2 {
public static void main(String[] args) {
new Test2().m1();
}
private synchronized void m1() {
System.out.println("外层");
new Test2().m2();
}
private synchronized void m2() {
System.out.println("中层");
new Test2().m3();
}
private synchronized void m3() {
System.out.println("内层");
}
}
2.效果如下
代码如下(示例):
外层
中层
内层
二、简单理解ReentrantLock
1.synchronized 引入 代码块
代码如下(示例):
public static void main(String[] args) {
LockTest1 test1 = new LockTest1();
test1.m1();
test1.m2();
}
public void m1() {
new Thread(()->{
lock.lock();
// 多次加锁 此线程没有问题 其它线程 就会因为 这里多次 加锁 然后 导致线程阻塞
// lock.lock();
try{
System.out.println(Thread.currentThread().getName()+"外层");
lock.lock();
try{
System.out.println(Thread.currentThread().getName()+"中层");
lock.lock();
try{
System.out.println(Thread.currentThread().getName()+"内层");
}finally {
lock.unlock();
}
}finally {
lock.unlock();
}
}finally {
lock.unlock();
}
},"q1").start();
}
public void m2(){
new Thread(()->{
lock.lock();
try{
System.out.println(Thread.currentThread().getName()+"第二次");
}finally {
lock.unlock();
}
},"q2").start();
}
2.效果如下
代码如下(示例):
q1外层
q1中层
q1内层
q2第二次
可重入锁的实现原理
使用 javap -c 命令 编译之后 会发现 一个monitenter 有 2个monitexit 是为了防止发生异常 造成 死锁
可重入锁实现 原理 Jvm 提供了一个 锁计数器 和 一个指向持有该锁的线程的指针 如果说目标锁对象的计数器不为零 如果锁对象的持有线程是该线程 那么jvm 就让 计数器+1 如果不是 则等待释放该锁 当执行 monitexit的时候 会将 锁计数器减一 直到为0 释放该锁
总结
提示:这里对文章进行总结:
以上就是今天要讲的内容,本文仅仅简单介绍了Synchronized 以及ReentrantLock的特性,在之后本人会常常更新希望大家支持!