Java锁:自旋锁

22 篇文章 0 订阅
4 篇文章 0 订阅
自旋锁
实现原理(while循环+CAS(compareAndSet))
  • 一个锁已经被一个线程锁持有,其他尝试获取该锁的线程并不会立即阻塞,而是采用循环的方式不停地尝试去获取锁,直至获取成功,跳出循环
  • 现实生活中的例子:公用洗衣机,一个人想去洗衣服,但是此时洗衣机正在被占用着,那么这个人有两种选择,要么一直在洗衣机前等待,等到该洗衣机洗完,另一种每隔一段时间再回来看看,洗衣机是否已经洗完
代码示例和解释
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 自旋锁:
 * 实现原理(while循环+CAS(compareAndSet))
 * 一个锁已经被一个线程锁持有,其他尝试获取该锁的线程并不会立即阻塞,而是采用循环的方式不停地尝试去获取锁,直至获取成功,跳出循环
 * 现实生活中的例子:公用洗衣机,一个人想去洗衣服,但是此时洗衣机正在被占用着,那么这个人有两种选择,要么一直在洗衣机前等待,等到该洗衣机洗完,另一种每隔一段时间再回来看看,洗衣机是否已经洗完
 */
public class SpinLock {
    
	public static void main(String[] args){
		SpinLockResource spinLockResource = new SpinLockResource();
    	new Thread(()->{
    		//t1线程获得锁
    		spinLockResource.getLock();
    		//睡眠5秒,让t2线程尝试获取锁
    		try {
				Thread.sleep(5000);
			} catch (Exception e) {
				e.printStackTrace();
			}
    		//t1线程释放锁
    		spinLockResource.removeLock();
    	},"t1").start();
    	
    	//当前main线程暂停一秒
    	try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    	
    	new Thread(()->{
    		//t2线程去获取锁
    		spinLockResource.getLock();
    		//睡眠1秒,t2线程获取完锁
    		try {
				Thread.sleep(1000);
			} catch (Exception e) {
				e.printStackTrace();
			}
    		//t2线程释放锁
    		spinLockResource.removeLock();
    	},"t2").start();
    	
    }
}

//资源类
class SpinLockResource{
	
	//原子引用线程,使用原子类的CAS方法
	AtomicReference<Thread> atomicThread = new AtomicReference<>();
	
	//获取锁方法
	public void getLock(){
		Thread thread = Thread.currentThread();//获取当前线程
		//atomicThread.compareAndSet(null, thread)
		//当前线程去和主内存中线程比较,如果此时主内存中线程为空,返回true,将当前线程设置进主内存中
		//初始atomicThread.compareAndSet(null, thread)为true,当前线程会设置进主内存,整个取反为false,不会进入while循环
		while(!atomicThread.compareAndSet(null, thread)){
			System.out.println(Thread.currentThread().getName()+"\t try to getLock...");
		}
		System.out.println(Thread.currentThread().getName()+"\t getLock......");
	}
	
	//释放锁资源的方法
	public void removeLock(){
		Thread thread = Thread.currentThread();//获取当前线程
		atomicThread.compareAndSet(thread, null);//主内存中为当前线程,将主内存中线程置为空,相当于释放了锁资源,供其他线程写入。
		System.out.println(Thread.currentThread().getName()+"\t removeLock......");
	}
	
}
打印结果:

t1线程获取锁之后,t2线程会循环尝试去获取锁,而不是一直阻塞
在这里插入图片描述
直到t1线程释放锁,t2线程才去跳出循环,获取锁
在这里插入图片描述
但是如果出现极端情况下,第一个线程一直没有释放锁,第二个线程不停地去循环,造成死循环,就会造成很大的cpu开销

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值