一、可重入锁与不可重入锁的区别
可重入锁和不可重入锁的最大区别在于,可重入锁允许同一个线程在获得锁之后再次获得该锁,而不可重入锁不允许。
在使用不可重入锁时,如果一个线程已经获得该锁,那么在该线程释放该锁之前,其他所有线程都无法获得这个锁。而在使用可重入锁时,如果一个线程已经获得锁,那么在该线程释放该锁之前,它可以再次获得该锁而不会被阻塞。
二、可重入锁的使用场景
可重入锁通常应用于递归或者嵌套的代码中。在代码嵌套调用的过程中,如果使用不可重入锁,那么程序将会阻塞,可能会导致死锁现象的发生。
举例来说,在使用不可重入锁时,如果在一个线程已经获得锁的情况下,又尝试获得该锁,那么这个线程将会被一直阻塞,直到另外一个线程释放该锁。而在使用可重入锁时,同一个线程可以多次获得锁,因此不会导致死锁现象的发生。
三、可重入锁的实现原理
可重入锁最常用的实现方式是通过计数器来实现的,每次获得锁时,计数器加1,每次释放锁时,计数器减1。只有当计数器为0时,其他线程才有机会获得该锁。这样就能够保证同一个线程可以多次获得该锁,而其他线程只有在该锁被彻底释放时才能获得该锁。
四、synchronized可重入锁
在Java语言中,synchronized关键字是一种可重入锁。这意味着如果一个线程已经获得了某个对象上的synchronized锁,那么它可以再次获得该对象锁而不会被阻塞。
synchronized锁的实现方式并不是通过计数器来实现的。它是通过线程持有的对象监视器(也可以称为锁对象)来实现的。当线程请求进入一段同步代码时,如果该锁没有被其他线程占用,那么该线程会获得该锁,同时锁对象的计数器会+1。如果同一线程再次请求该锁,那么线程可以再次获得该锁,同时计数器也会再次+1。当线程执行完同步代码块并释放锁时,该线程持有的锁对象的计数器会-1。只有当该计数器的值为0时,锁对象才会被解锁,这样其他线程才有机会获得该锁。
五、可重入锁和不可重入锁的区别
1、可重入锁允许同一个线程在获得锁之后再次获得该锁,而不可重入锁不允许。
2、在使用不可重入锁时,如果一个线程已经获得该锁,那么在该线程释放该锁之前,其他所有线程都无法获得这个锁。而在使用可重入锁时,如果一个线程已经获得锁,那么在该线程释放该锁之前,它可以再次获得该锁而不会被阻塞。
3、可重入锁通常用于递归嵌套的代码中,而不可重入锁一般只用于独占式地获得资源。
示例代码
// 可重入锁的示例
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockDemo {
private static final ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
work();
}
}).start();
}
}
private static void work() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "获得了锁");
nestedWork();
} finally {
lock.unlock();
}
}
private static void nestedWork() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "再次获得了锁");
} finally {
lock.unlock();
}
}
}
// 不可重入锁的示例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class NonReentrantLockDemo {
private static final Lock lock = new ReentrantLock();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
work();
}
}, "Thread-A").start();
new Thread(new Runnable() {
@Override
public void run() {
work();
}
}, "Thread-B").start();
}
private static void work() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "获得了锁");
nestedWork();
} finally {
lock.unlock();
}
}
private static void nestedWork() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "尝试获得锁但被阻塞了");
} finally {
lock.unlock();
}
}
}
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/199136.html
微信扫一扫
支付宝扫一扫