[关闭]
@x-power 2022-12-27T05:17:58.000000Z 字数 1065 阅读 682

重入, 中断, 公平, 读写锁

操作系统


可重入锁 / 不可重入锁

可重入锁

Wikipedia: 若一个程序或子程序可以" 在任意时刻被打断然后操作系统调度之行另一端代码, 这段代码又调用了该子程序而不会出错 " 则称其为可重入锁. 即当该子程序正在运行时, 执行线程可以再次进入并执行它, 仍然获得符合设计时的预期结果. 与多线程并发执行的线程安全不同, 可重入强调对单个线程执行时重新进入同一个子程序仍然是安全的.

某个线程试图获取一个已经由他自己持有的锁. 这个请求可以成功, 那么此时的锁就是可重入锁, 重入锁的这种机制也说明了它是以 "线程" 为粒度获取锁, 而不是以"调用"为粒度.

重入锁一个常见的实现方式是, 为每一个锁关联一个持有者和持有计数值, 当计数值为0时, 这个锁会被认为没有被任何线程持有, 当线程请求一个未被持有的锁的时候, JVM会把这个锁给这个线程, 并记下这个锁的持有者, 同时计数器值置为1, 如果同一个线程再次获取这个锁, 计数值递增一. 当线程同步代码块时, 计数值将递减一, 当为0时, 锁被释放. 常见的重入锁有SynchronizedReenTrantLock

不可重入锁

不可重入锁和可重入锁相反, 就是同一个线程多次请求同一把锁就会出现死锁. 可以看到父类和子类的MethodA方法的synchronized持有的锁都是SuperSynObj.class, 他们两个持有同一把锁, 如果Synchronized不是可重入锁的话, 会在代码的的注释出 出现死锁的状况.

  1. class SuperSynObj {
  2. public synchronized void methodA() {
  3. synchronized (SuperSynObj.class) {
  4. System.out.println("Super class running");
  5. }
  6. }
  7. }
  8. class SynObj extends SuperSynObj {
  9. @Override
  10. public void methodA() {
  11. synchronized (SuperSynObj.class) {
  12. System.out.println("methodA");
  13. try {
  14. super.methodA(); // 不是重入锁将在 此处 出现死锁.
  15. Thread.sleep(5000);
  16. super.methodA();
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. }
  22. }
  23. class Dog {
  24. public static void main(String[] args) {
  25. new SynObj().methodA();
  26. }
  27. }

现在模拟一个不可重入的自旋锁.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注