自旋锁spinlock:
指尝试获取锁的线程不会立即阻塞,而是菜用循环的方式去获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗cpu。 例如前面说的CAS,就是一个自旋锁。
手写自旋锁:
package learn;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author:tao.liu
* @Date:2020/1/2
*/
public class SpinlockDemo {
// AtomicReference对象创建初始值为null
private AtomicReference<Thread> threadAtomicReference = new AtomicReference<>();
public void lock() {
Thread currentThread = Thread.currentThread();
// 模拟自旋
while (!threadAtomicReference.compareAndSet(null, currentThread)) {
}
System.out.println(Thread.currentThread().getName() + "\t获取厨房锁钥匙");
}
public void unLock() {
Thread currentThread = Thread.currentThread();
threadAtomicReference.compareAndSet(currentThread, null);
System.out.println(Thread.currentThread().getName() + "\t释放厨房锁");
}
public static void main(String[] args) {
SpinlockDemo spinlockDemo = new SpinlockDemo();
new Thread(() -> {
spinlockDemo.lock();
try {
System.out.println(Thread.currentThread().getName() + "\t在厨房做饭");
TimeUnit.SECONDS.sleep(8);
System.out.println(Thread.currentThread().getName() + "\t饭做好了可以吃了");
} catch (InterruptedException e) {
e.printStackTrace();
}
spinlockDemo.unLock();
}, "妈妈").start();
new Thread(() -> {
spinlockDemo.lock();
try {
System.out.println(Thread.currentThread().getName() + "\tT1饭好了可以进去吃饭");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + "\tT2吃过饭");
} catch (InterruptedException e) {
e.printStackTrace();
}
spinlockDemo.unLock();
}, "儿子").start();
}
}
结果如下: