聊聊java的自旋锁以及手撸一个自旋锁

    前几天的一篇文章,谈到UnSafe类CAS思想时,说的其原理就是自旋锁(spinlock),那什么是自旋锁呢,从字面解释就是自我旋转,是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点就是循环会消耗CPU,下边这段代码是UnSafe的实现CAS的源码,使用do...while实现了一个自旋锁,循环着获取主内存中的值。

    public final int getAndAddInt(Object o, long offset, int delta) {
        int v;
        do {
            v = getIntVolatile(o, offset);
        } while (!weakCompareAndSetInt(o, offset, v, v + delta));
        return v;
    }

    概念我们说完,动手撸一个自旋锁的demo,创建两个方法,一个是myLock,另一个是myUnLock,创建名为t1和t2的两个线程分别调用这两个方法。

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

public class SpinLockDemo {

    AtomicReference atomicReference = new AtomicReference<>();

    public void myLock() {
        Thread thread = Thread.currentThread();
        System.err.println(Thread.currentThread().getName() + "\t invoked myLock");
        while (!atomicReference.compareAndSet(null, thread)) {

        }

    }

    public void myUnLock() {
        Thread thread = Thread.currentThread();
        atomicReference.compareAndSet(thread, null);
        System.err.println(Thread.currentThread().getName() + "\t invoked myUnLock");
    }

    public static void main(String[] args) throws Exception {
        SpinLockDemo spinLockDemo = new SpinLockDemo();
        new Thread(() -> {
            spinLockDemo.myLock();

            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            spinLockDemo.myUnLock();
        }, "t1").start();

        TimeUnit.SECONDS.sleep(1);

        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinLockDemo.myLock();
            spinLockDemo.myUnLock();
        }, "t2").start();

    }

}

    自旋锁的好处就是减少线程上下文切换的消耗,缺点就是当一个线程一直占用锁的时候,其他线程都在循环等待先抢到锁的线程释放锁会消耗CPU,好了,今天内容到这,下篇见。

你可能感兴趣的:(java,java自旋锁,手撸自旋锁)