自旋锁:
是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗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<Thread> 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。
网友评论