重入, 中断, 公平, 读写锁
重入, 中断, 公平, 读写锁
标签(空格分隔): 操作系统
可重入锁 / 不可重入锁
可重入锁
Wikipedia: 若一个程序或子程序可以" 在任意时刻被打断然后操作系统调度之行另一端代码, 这段代码又调用了该子程序而不会出错 " 则称其为可重入锁. 即当该子程序正在运行时, 执行线程可以再次进入并执行它, 仍然获得符合设计时的预期结果. 与多线程并发执行的线程安全不同, 可重入强调对单个线程执行时重新进入同一个子程序仍然是安全的.
某个线程试图获取一个已经由他自己持有的锁. 这个请求可以成功, 那么此时的锁就是可重入锁, 重入锁的这种机制也说明了它是以 "线程" 为粒度获取锁, 而不是以"调用"为粒度.
重入锁一个常见的实现方式是, 为每一个锁关联一个持有者和持有计数值, 当计数值为0时, 这个锁会被认为没有被任何线程持有, 当线程请求一个未被持有的锁的时候, JVM会把这个锁给这个线程, 并记下这个锁的持有者, 同时计数器值置为1, 如果同一个线程再次获取这个锁, 计数值递增一. 当线程同步代码块时, 计数值将递减一, 当为0时, 锁被释放. 常见的重入锁有Synchronized 和ReenTrantLock
不可重入锁
不可重入锁和可重入锁相反, 就是同一个线程多次请求同一把锁就会出现死锁. 可以看到父类和子类的
MethodA方法的synchronized持有的锁都是SuperSynObj.class, 他们两个持有同一把锁, 如果Synchronized不是可重入锁的话, 会在代码的的注释出 出现死锁的状况.
class SuperSynObj {
public synchronized void methodA() {
synchronized (SuperSynObj.class) {
System.out.println("Super class running");
}
}
}
class SynObj extends SuperSynObj {
@Override
public void methodA() {
synchronized (SuperSynObj.class) {
System.out.println("methodA");
try {
super.methodA(); // 不是重入锁将在 此处 出现死锁.
Thread.sleep(5000);
super.methodA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Dog {
public static void main(String[] args) {
new SynObj().methodA();
}
}
现在模拟一个不可重入的自旋锁.

浙公网安备 33010602011771号