Java锁之自旋锁

自旋锁: 是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。
前面讲CAS的文章中其实就已经有涉及到自旋锁相关的知识,只是当时没有过多的去说,比如下面的代码:

public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;
}

那么我们就来照猫画虎实现一个小案例

public class SpinLockTest {
    public static void main(String[] args) {
        SpinLock lock = new SpinLock();
        new Thread(() -> {
            lock.lock();
            try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}
            lock.unLock();
        }, "t1").start();
        try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}
        new Thread(() -> {
            lock.lock();
            lock.unLock();
        }, "t2").start();
    }
}

class SpinLock {
    AtomicReference atomicReference = new AtomicReference<>();
    public void lock() {
        System.out.println(Thread.currentThread().getName() + " called lock()");
        Thread thread = Thread.currentThread();
        do {
//            System.out.println("尝试获取锁...");
        } while (!atomicReference.compareAndSet(null, thread));
    }
    public void unLock() {
        Thread thread = Thread.currentThread();
        atomicReference.compareAndSet(thread, null);
        System.out.println(Thread.currentThread().getName() + " ******called unLock()");
    }
}

运行结果:

t1 called lock()
t2 called lock()
t1 ******called unLock()
t2 ******called unLock()

观察上面的代码,我们没有使用 synchronized关键字,也没有使用 ReentrantLok加锁解锁,而是利用了原子引用以及CAS的 compareAndSet() 方法模拟实现了一个简单的demo。

你可能感兴趣的:(Java锁之自旋锁)