一、可重入锁与不可重入锁的区别
可重入锁和不可重入锁的最大区别在于,可重入锁允许同一个线程在获得锁之后再次获得该锁,而不可重入锁不允许。
在使用不可重入锁时,如果一个线程已经获得该锁,那么在该线程释放该锁之前,其他所有线程都无法获得这个锁。而在使用可重入锁时,如果一个线程已经获得锁,那么在该线程释放该锁之前,它可以再次获得该锁而不会被阻塞。
二、可重入锁的使用场景
可重入锁通常应用于递归或者嵌套的代码中。在代码嵌套调用的过程中,如果使用不可重入锁,那么程序将会阻塞,可能会导致死锁现象的发生。
举例来说,在使用不可重入锁时,如果在一个线程已经获得锁的情况下,又尝试获得该锁,那么这个线程将会被一直阻塞,直到另外一个线程释放该锁。而在使用可重入锁时,同一个线程可以多次获得锁,因此不会导致死锁现象的发生。
三、可重入锁的实现原理
可重入锁最常用的实现方式是通过计数器来实现的,每次获得锁时,计数器加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(); } } }