java重入锁 自旋锁_可重入锁 自旋锁,看这一篇就够了!

在多线程编程中,锁是常用地控制并发的机制,对于临界区的资源,需要保证线程之间互斥地访问。

1. 可重入锁

可重入锁,也叫做递归锁,指的是多次对同一个锁进行加锁操作,都不会阻塞线程。实现思路:记录当前锁正在被哪个线程使用,采用计数来统计lock和unlock的调用次数。正常情况下,lock和unlock的调用次数应该相等,如果不相等就会死锁。

public class Test implements Runnable {

ReentrantLock lock = new ReentrantLock(); //定义一个可重入锁

public void get() {

lock.lock(); //第一次调用lock()

System.out.println(Thread.currentThread().getId());

set();

lock.unlock();

}

public void set() {

lock.lock(); //第二次调用lock(),而且会成功,说明lock是可重入锁

System.out.println(Thread.currentThread().getId());

lock.unlock();

}

@Override

public void run() {

get();

}

public static void main(String[] args) {

Test ss = new Test();

new Thread(ss).start();

new Thread(ss).start();

new Thread(ss).start();

}

}

2. 自旋锁

首先,看看初级的自旋锁实现方式:

public class SpinLock {

private AtomicReference owner =new AtomicReference<>();

public void lock(){

Thread current = Thread.currentThread();

while(!owner.compareAndSet(null, current)){

}

}

public void unlock (){

Thread current = Thread.currentThread();

owner.compareAndSet(current, null);

}

}

实现思路:通过CAS(CompareAndSet)原子操作来更新变量。如果CAS返回true,表示获得了锁;否则,需要通过while循环检查,直到获得锁为止,这也是为什么叫做自旋锁的原因,需要不停的尝试获取锁。

2.1 初级版本的问题

同一线程前后两次调用lock(),会导致第二次调用lock时进行自旋,产生了死锁(因为第一次调用lock()之后,还没有unlock),说明这个锁不是可重入的。

如果问题一已经解决,当第一次调用unlock()时,就已经将锁释放了。实际上不应释放锁。

2.2 解决方案

针对问题一:在lock函数内,应验证线程是否为已经获得锁的线程

针对问题二:采用计数进行统计

public class SpinLock {

private AtomicReference owner =new AtomicReference<>();

private int count =0;

public void lock(){

Thread current = Thread.currentThread();

if(current==owner.get()) {

count++;

return ;

}

while(!owner.compareAndSet(null, current)){

}

}

public void unlock (){

Thread current = Thread.currentThread();

if(current==owner.get()){

if(count!=0){

count--;

}else{

owner.compareAndSet(current, null);

}

}

}

}

3. 参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值