16.各种锁

各种锁

1、公平锁,非公平锁

公平锁:非常公平,不能插队

非公平锁:非常不公平,可以插队(默认都是非公平)

//非公平锁
ReentrantLock reentrantLock = new ReentrantLock();

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

//公平锁
 ReentrantLock reentrantLock = new ReentrantLock(true);

2、可重入锁

可重入锁(递归锁)

Synchronized版

public class SyncDemo {
    public static void main(String[] args) {
        new Thread(() -> {
            Phone phone = new Phone();
            phone.sms();
        },"A" ).start();

        new Thread(() -> {
            Phone phone = new Phone();
            phone.sms();
        },"B" ).start();
    }
}

class Phone {
    public synchronized void sms() {
        System.out.println(Thread.currentThread().getName() + " sms");
        call();
    }

    public synchronized void call() {
        System.out.println(Thread.currentThread().getName() + " call");
    }
}

Lock版

public class LockDemo {
    public static void main(String[] args) {
        Phone1 phone = new Phone1();
        new Thread(() -> {
            phone.sms();
        }, "A").start();

        new Thread(() -> {
            phone.sms();
        }, "B").start();
    }
}

//
class Phone1 {
    ReentrantLock lock = new ReentrantLock();

    public void sms() {
        lock.lock();//lock和unlock必须成对出现,有加锁就必须有解锁,否则死锁
        try {
            System.out.println(Thread.currentThread().getName() + " sms");
            call();//这里也有锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void call() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " call");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
3、自旋锁

自写自旋锁

/*
 * 自定义自旋锁
 * */
public class MyLock {
    AtomicReference<Thread> reference = new AtomicReference<>();
    //加锁
    public void myLock() {
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + " mylock");
        while (!reference.compareAndSet(null, thread)) {

        }
    }

    //解锁
    public void myUnLock() {
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + " myunlock");
        reference.compareAndSet(thread, null);

    }
}

测试

public class MyLockTest {
    public static void main(String[] args) throws InterruptedException {
        MyLock lock = new MyLock();
        new Thread(()->{
            lock.myLock();
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.myUnLock();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(1);//保证A先获取到锁

        new Thread(()->{
            lock.myLock();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.myUnLock();
            }
        },"B").start();
    }
}

总结:A先拿到锁,执行完,解锁,B才能拿到锁

4、死锁

死锁代码

public class DeadLock implements Runnable {
    private String a;
    private String b;

    public DeadLock(String a, String b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public void run() {
        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 + ",要去获取锁" + a);
            }
        }
    }
}

测试

//程序会一直卡着,死锁
//T1持有锁lockA,要去获取锁lockB
//T2持有锁lockB,要去获取锁lockA
public class DeadLockTest {
    public static void main(String[] args) {
        new Thread(new DeadLock("lockA", "lockB"), "T1").start();
        new Thread(new DeadLock("lockB", "lockA"), "T2").start();
    }
}

解决问题

  1. jps -l定位进程号

    PS D:\tools\juc> jps -l
    11168 sun.tools.jps.Jps
    6784 org.jetbrains.idea.maven.server.RemoteMavenServer36
    832 lock.deadlock.DeadLockTest
    4316
    4748 org.jetbrains.jps.cmdline.Launcher
    PS D:\tools\juc>
    
  2. jstack 进程号查看进程信息

    发现:互相持有对方的锁

    "T2":
            at lock.deadlock.DeadLock.run(DeadLock.java:24)
            - waiting to lock <0x000000076b8db678> (a java.lang.String)
            - locked <0x000000076b8db6b0> (a java.lang.String)
            at java.lang.Thread.run(Thread.java:748)
    "T1":
            at lock.deadlock.DeadLock.run(DeadLock.java:24)
            - waiting to lock <0x000000076b8db6b0> (a java.lang.String)
            - locked <0x000000076b8db678> (a java.lang.String)
            at java.lang.Thread.run(Thread.java:748)
    
posted @   jpy  阅读(2)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示