import java.util.concurrent.atomic.AtomicStampedReference;
/**
* Function:自旋锁演示demo
*
* A线程加锁后沉睡5秒然后解锁,B线程加锁解锁
*
* 请手写一个自旋锁
*
* @author liubing
* Date: 2019/6/6 5:17 PM
* @since JDK 1.8
*/
public class SpinLockDemo {
//定一个一个带时间戳的原子线程类,给的默认值是false
static AtomicStampedReference<Thread> atomicThread = new AtomicStampedReference<>(null,1);
public static void main(String args[]){
new Thread(()->{
myLock();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
myUnLock();
}
},"AAA").start();
new Thread(()->{
myLock();
myUnLock();
},"BBB").start();
}
public static void myLock(){
Thread thread = Thread.currentThread();
System.out.println(thread.getName()+" come in,version is "+atomicThread.getStamp());
while(!atomicThread.compareAndSet(null,thread,1,2)){
// System.out.println("加锁失败");
}
System.out.println(thread.getName()+"加锁成功");
System.out.println(thread.getName()+" come out,version is "+atomicThread.getStamp());
}
public static void myUnLock(){
Thread thread = Thread.currentThread();
System.out.println(thread.getName()+" come in,version is "+atomicThread.getStamp());
while(!atomicThread.compareAndSet(thread,null,2,1)){
// System.out.println("解锁失败");
}
System.out.println(thread.getName()+"解锁成功");
System.out.println(thread.getName()+" come out,version is "+atomicThread.getStamp());
}
}
输出结果
AAA come in,version is 1
BBB come in,version is 1
AAA加锁成功
AAA come out,version is 2
AAA come in,version is 2
AAA解锁成功
BBB加锁成功
BBB come out,version is 2
BBB come in,version is 2
BBB解锁成功
BBB come out,version is 1
AAA come out,version is 2
Process finished with exit code 0
由此可见,B线程进入myLock的时候atomicThread的版本号为2,显然对于B线程来说是无法进行加锁的,无法加锁只能一直循环循环循环,询问A线程到我了吗到我了吗,A线程沉睡五秒后开始解锁,解锁完毕之后,B线程第n次循环之后再来问到我了吗,A线程告诉B到你了,然后B开始加锁,加锁完了之后再开始解锁。在A完成解锁之前B线程的期望值跟期望版本号一直都不是跟内存中存在的值与版本号对应,所以,B一直都是处于循环等待的状态,等A完事儿之后,期望值跟期望版本号跟内存中的值跟版本号都一样了,B线程才开始加锁,B线程进入mylock的时候版本号是2,出来的时候版本号是1。这就是很明显的自旋。
自旋锁原理与实现

2045

被折叠的 条评论
为什么被折叠?



