【JUC】多线程锁

synchronized锁的对象

Java中每个对象都可以作为锁。具体表现为以下三种形式:

  1. 对于普通同步方法,锁是当前实例对象this
  2. 对于静态同步方法,锁是当前类字节码,Class对象
  3. 对于同步方法块,锁是synchronized括号里配置的对象

公平锁和非公平锁

非公平锁

 private final ReentrantLock lock = new ReentrantLock();
 // private final ReentrantLock lock = new ReentrantLock(false);

非公平锁,可能导致其他线程饿死。(一个人把活全干了,不问有没有人,直接抢)
效率高

公平锁

private final ReentrantLock lock = new ReentrantLock(true);

阳光普照,问一下有人没,有人就排队
效率相对低

可重入锁/递归锁

可重入锁特点演示:打开外层锁后,还可以继续打开内层锁

public static void main(String[] args) {
    
    
        Object o = new Object();
        new Thread(()->{
    
    
            synchronized (o) {
    
    
                System.out.println(Thread.currentThread().getName() + "外层");
                synchronized (o) {
    
    
                    System.out.println(Thread.currentThread().getName() + "内层");
                }
            }
        },"AA").start();
}

可重入锁可以实现重复递归调用

public class SyncLockDemo {
    
    

    public synchronized void add(){
    
    
        add();
    }
    
    public static void main(String[] args) {
    
    
        new SyncLockDemo().add();
    }
}

死锁

什么是死锁:

两个或两个以上的进程, 因为争夺资源而造成互相等待的现象,如果没有外力干涉,他们无法再执行下去

产生死锁的原因

  1. 系统资源不足
  2. 进程运行推进顺序不合适
  3. 资源分配不当

死锁例子

public class DeadLock {
    
    

    //创建两个对象
    static Object a = new Object();
    static Object b = new Object();

    public static void main(String[] args) {
    
    
        new Thread(()->{
    
    
            synchronized (a) {
    
    
                System.out.println(Thread.currentThread().getName() + "持有锁a, 试图获取锁b");
                try {
    
    
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                synchronized (b) {
    
    
                    System.out.println(Thread.currentThread().getName() + "获取到锁b");
                }
            }
        },"AA").start();

        new Thread(()->{
    
    
            synchronized (b) {
    
    
                System.out.println(Thread.currentThread().getName() + "持有锁b, 试图获取锁a");
                try {
    
    
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                synchronized (a) {
    
    
                    System.out.println(Thread.currentThread().getName() + "获取到锁a");
                }
            }
        },"BB").start();
    }
}

验证是否是死锁

  1. jps -l 得到正在运行的程序进程号
  2. jstack 进程号 可以验证是否是死锁发生

猜你喜欢

转载自blog.csdn.net/weixin_44179010/article/details/123193167