手写死锁和自旋锁

135 阅读1分钟

死锁

线程1 在获取到 lock1 锁之后没有释放,接着要获取 lock2 锁,
同时,线程2 在获取到 lock2 锁之后没有释放,接着要获取 lock1 锁,
这就导致两个线程都持有对方想要获取的锁而不释放,都获取不到下一个锁,最终导致无法释放锁而形成死锁。

import java.util.concurrent.TimeUnit;

public class DeadLockDemo {

    public static final Object lock1 = new Object();
    public static final Object lock2 = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (lock1) {
                System.out.println(Thread.currentThread().getName() + "获取到lock1锁,准备获取lock2锁");
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock2) {
                    System.out.println(Thread.currentThread().getName() + "获取到lock2锁");
                }
                System.out.println(Thread.currentThread().getName() + "释放lock2锁");
            }
            System.out.println(Thread.currentThread().getName() + "释放lock1锁");
        }, "t1").start();

        new Thread(() -> {
            synchronized (lock2) {
                System.out.println(Thread.currentThread().getName() + "获取到lock2锁,准备获取lock1锁");
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1) {
                    System.out.println(Thread.currentThread().getName() + "获取到lock1锁");
                    System.out.println(Thread.currentThread().getName() + "释放lock1锁");
                }
            }
            System.out.println(Thread.currentThread().getName() + "释放lock2锁");
        }, "t2").start();
    }

}

自旋锁

使用 AtomicReference 实现自旋锁

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

public class SpinLockDemo {

    AtomicReference<Thread> atomicReference = new AtomicReference<>();

    public void MyLock() {
        System.out.println(Thread.currentThread().getName() + " come in");
        while (!atomicReference.compareAndSet(null, Thread.currentThread())) {

        }
        System.out.println(Thread.currentThread().getName() + " 获取锁成功");
    }

    public void MyUnLock() {
        while (!atomicReference.compareAndSet(Thread.currentThread(), null)) {

        }
        System.out.println(Thread.currentThread().getName() + " 释放锁");
    }

    public static void main(String[] args) {
        SpinLockDemo spinLockDemo = new SpinLockDemo();

        new Thread(() -> {
            // 获取锁
            spinLockDemo.MyLock();
            try {
                // 拿到锁使用3秒钟
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 释放锁
            spinLockDemo.MyUnLock();
        }, "t1").start();

        new Thread(() -> {
            spinLockDemo.MyLock();
            spinLockDemo.MyUnLock();
        }, "t2").start();
    }

}