java中锁的种类--重入锁丶自旋锁


1.重入锁

重入锁又名递归锁,当同一个线程在外层方法已经获取锁的时候,再进入内层方法时会自动获取该锁

  • 优点: 可以一定程度避免死锁

  • java中的ReentrantLockSynchronized都是重入锁

简单认知

public class Reentrant{
    public synchronized void outOne(){//锁对象为this
        System.out.println("One");
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //进入该方法内时已经获取到了锁(this),此时再调用outTwo()方法时会自动获取到锁(this)
        outTwo();
    }
    public synchronized void outTwo(){//锁对象为this
        System.out.println("Two");
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //测试
    @Test
    public void test(){
        //执行测试,因为synchronized为重入锁,因此不会出现死锁的情况
        new Thread(new Runnable() {
            @Override
            public void run() {
                new Reentrant().outOne();
            }
        }).start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2.自旋锁(spinlock)

自旋锁是非阻塞锁,指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁

  • 优点: 不会有线程状态切换,因此响应快
  • 缺点: 循环会消耗cpu,死锁问题
  • 注意:递归程序使用自旋锁时,不能在持有自旋锁时调用自己,也不能在递归调用时试图获得相同的自旋锁

应用场景

  • 使用自旋锁(spinlock)时,临界区要尽量短,不要有显式或者隐式的系统调用(如读写文件操作)
  • 临界区: 一个访问共用资源的程序片段,当有线程进入临界区时,其他线程或进程必须等待
  • 存在大量线程,竞争激烈时,不适合使用自旋锁(占用cpu时间)

自旋锁的实现

public class SpinLock {
  private AtomicReference<Thread> sign =new AtomicReference<>();

  public void lock(){
    Thread current = Thread.currentThread();
    while(!sign .compareAndSet(null, current)){
    }//当第二个线程调用lock方法时,导致循环一直被执行(自旋),直到第一个线程调用unlock才结束
  }

  public void unlock (){
    Thread current = Thread.currentThread();
    sign .compareAndSet(current, null);
  }
}

文章作者: Bryson
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Bryson !
评论
 上一篇
下一篇 
设计模式-模版设计模式 设计模式-模版设计模式
模版设计模式的定义 定义一个操作中的算法的框架,而将一些步骤放到子类中,是的子类可以不改变该算法框架即可重定义该算法的某些特定步骤 简单实例: 计算程序运行时间的模版 注意: 一般模版方法都会加上final关键字,不允许被重写 abst
2018-05-19
  目录