目录
- 一、重入锁的理解
- 二、方式一:使用synchronized演示例重入锁示例
- 三、方式二:使用ReentrantLock演示例重入锁示例
- 四、使用ReentrantLock演示例重入锁示例(加锁和释放次数不一样导致的死锁)
一、重入锁的理解
- 某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。
- 可重入锁,也叫做递归锁。指的是同一线程外层函数获得锁之后,内层递归函数仍然能够获得该锁的代码。
- 在同一个线程,在外层方法获取锁的时候,进入内层方法时会自动获取锁。
- synchronized和ReentrantLock都是可重入的。
- 可重入锁最大的作用就是避免死锁。
- 重入降低了编程复杂性。
二、方式一:使用synchronized演示例重入锁示例
1、代码
package com.xz.thread.t5;
/**
* @description: 第一种方式:使用synchronized演示例重入锁
* @author: xz
*/
public class Demo3 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized (this){
System.out.println("第1次获取锁,这个锁是:" + this);
int index=1;
while(true){
synchronized (this){
System.out.println("第" + (++index) + "次获取锁,这个锁是:" + this);
}
if (index == 10) {
break;
}
}
}
}
}).start();
}
}
2、输出结果
3、结论
- 由第2步截图可知,没有发生死锁,可以多次获取相同的锁。
三、方式二:使用ReentrantLock演示例重入锁示例
1、使用ReentrantLock的注意点
- ReentrantLock 和 synchronized 不一样,需要手动释放锁,所以使用 ReentrantLock的时候一定要手动释放锁,并且加锁次数和释放次数要一样。
2、代码
package com.xz.thread.t5;
import java.util.concurrent.locks.ReentrantLock;
/**
* @description: 第一种方式:使用ReentrantLock演示例重入锁
* @author: xz
*/
public class Demo4 {
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
new Thread(new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
System.out.println("第1次获取锁,这个锁是:" + reentrantLock);
int index=1;
while (true) {
try {
reentrantLock.lock();
System.out.println("第" + (++index) + "次获取锁,这个锁是:" + reentrantLock);
if (index == 10) {
break;
}
}finally {
reentrantLock.unlock();
}
}
} finally {
reentrantLock.unlock();
}
}
}).start();
}
}
3、输出结果
4、结论
- 由第3步截图可知,没有发生死锁,可以多次获取相同的锁。
四、使用ReentrantLock演示例重入锁示例(加锁和释放次数不一样导致的死锁)
1、代码
package com.xz.thread.t5;
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;
/**
* @description: 使用ReentrantLock演示例重入锁(加锁和释放次数不一样导致的死锁)
* @author: xz
*/
public class Demo5 {
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
//第一个线程
new Thread(new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
System.out.println("第1次获取锁,这个锁是:" + reentrantLock);
int index = 1;
while (true) {
try {
reentrantLock.lock();
System.out.println("第" + (++index) + "次获取锁,这个锁是:" + reentrantLock);
try {
Thread.sleep(new Random().nextInt(200));
} catch (InterruptedException e) {
e.printStackTrace();
}
if (index == 10) {
break;
}
} finally {
//lock.unlock();// 这里故意注释,实现加锁次数和释放次数不一样
}
}
} finally {
reentrantLock.unlock();
}
}
}).start();
//第二个线程
new Thread(new Runnable() {
@Override
public void run() {
try {
reentrantLock.lock();
for (int i = 0; i < 20; i++) {
System.out.println("threadName:" + Thread.currentThread().getName());
try {
Thread.sleep(new Random().nextInt(200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
reentrantLock.unlock();
}
}
}).start();
}
}
2、输出结果
3、结论
- 由第3步截图可知,由于第一个线程加锁次数和释放次数不一样,导致第二个线程始终无法获取到锁,一直在等待。