什么是自旋锁
它是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。
但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。
具体实现
/**
* @author: code duck
* @create: 2020-08-31 09:37
**/
public class SpinLock {
AtomicReference<Thread> reference = new AtomicReference<>();
public void lock() {
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + "尝试获得锁");
while (!reference.compareAndSet(null, thread)){
// 制造循环,阻塞代码.除非当前线程使用unlock()方法调用CAS方法,才会跳出循环
};
System.out.println(thread.getName() + "获取到了锁");
}
public void unlock() {
Thread thread = Thread.currentThread();
reference.compareAndSet(thread, null);
System.out.println(thread.getName() + "释放锁");
}
public static void main(String[] args) {
SpinLock lock = new SpinLock();
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " do something...");
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "线程1").start();
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " do something...");
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "线程2").start();
}
}
程序运行结果:
线程1尝试获得锁
线程2尝试获得锁
线程1获取到了锁
线程1 do something...
线程1释放锁
线程2获取到了锁
线程2 do something...
线程2释放锁