码迷,mamicode.com
首页 > 其他好文 > 详细

重入锁

时间:2019-02-01 12:22:20      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:++   进入   因此   ring   imp   高级功能   shu   cas   关键字   

重入锁

  • 重入锁指的是当前线成功获取锁后,如果再次访问该临界区,则不会对自己产生互斥行为。
  • Java中对ReentrantLock和synchronized都是可重入锁,synchronized由jvm实现可重入即使,ReentrantLock都可重入性基于AQS实现。
  • ReentrantLock还提供公平锁和非公平锁两种模式。
  • 重入锁的基本原理是判断上次获取锁的线程是否为当前线程,如果是则可再次进入临界区,如果不是,则阻塞。
ReentrantLock
  • 在JDK5.0版本之前,重入锁的性能远远好于synchronized关键字,JDK6.0版本之后synchronized 得到了大量的优化,二者性能也不分伯仲,但是重入锁是可以完全替代synchronized关键字的。除此之外,重入锁又自带一系列高逼格UBFF:可中断响应、锁申请等待限时、公平锁。另外可以结合Condition来使用,使其更是逼格满满。
package cas;

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

public class MyThread  extends Thread  {
    public static ReentrantLock lock = new ReentrantLock();
    public static int i = 0;

    public MyThread(String name) {
        super.setName(name);
    }

    @Override
    public void run() {
        for (int j = 0; j < 100; j++) {
            lock.lock();
            try {
                System.out.println(this.getName() + " " + i);
                i++;
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        MyThread test1 = new MyThread("thread1");
        MyThread test2 = new MyThread("thread2");

        test1.start();
        test2.start();
        test1.join();
        test2.join();
        System.out.println(i);
    }
}
  • 用法上可以看出,与synchronized相比, ReentrantLock就稍微复杂一点。因为必须在finally中进行解锁操作,如果不在 finally解锁,有可能代码出现异常锁没被释放,
  • ReentrantLock并不是一种替代内置加锁的方法,而是作为一种可选择的高级功能。ReentrantLock在功能上更加丰富,它具有可重入、可中断、可限时、公平锁等特点。
  • ReentrantLock 实现了 Lock interface
  • 特点
    • 可重入:可以反复得到相同的一把锁,它有一个与锁相关的获取计数器,如果拥有锁的某个线程再次得到锁,那么获取计数器就加1,然后锁需要被释放两次才能获得真正释放(重入锁)。
    • 与synchronized不同的是,ReentrantLock对中断是有响应的.synchronized一旦尝试获取锁就会一直等待直到获取到锁。
    • 可限时
      • 超时不能获得锁,就返回false,不会永久等待构成死锁
      • 使用lock.tryLock(long timeout, TimeUnit unit)来实现可限时锁,参数为时间和单位。
        ```
        public class TryLockTest extends Thread {

    public static ReentrantLock lock = new ReentrantLock();

    public TryLockTest(String name){
    super(name);
    }

    @Override
    public void run() {
    try {
    if (lock.tryLock(5, TimeUnit.SECONDS)) {
    Thread.sleep(6000);
    } else {
    System.out.println(this.getName() + " get lock failed");
    }
    } catch (Exception e) {
    } finally {
    if (lock.isHeldByCurrentThread()) {
    System.out.println("lock.isHeldByCurrentThread: " + this.getName());
    lock.unlock();
    }
    }
    }

    public static void main(String[] args) {
    TryLockTest t1 = new TryLockTest("TryLockTest1");
    TryLockTest t2 = new TryLockTest("TryLockTest2");

      t1.start();
      t2.start();

    }

}



##### 实现ReentrantLock公平锁
- 一般意义上的锁是不公平的,不一定先来的线程能先得到锁,后来的线程就后得到锁。不公平的锁可能会产生饥饿现象。
- 公平锁的意思就是,这个锁能保证线程是先来的先得到锁。虽然公平锁不会产生饥饿现象,但是公平锁的性能会比非公平锁差很多。
- synchronized是作为Java关键字是依赖于JVM实现,Java团队应该是优先考虑性能问题,因此synchronized是非公平锁。
- 使用方法:

public ReentrantLock(boolean fair)

public static ReentrantLock fairLock = new ReentrantLock(true);
```

隐式锁和显式锁
  • 隐式锁:隐式获取锁,synchronized是它的代表,使用者不需要关心其内部锁的获取和释放,所有的锁的相关操作都由具体的关键字完成;
  • 显式锁:显示地获取锁,Lock是它的代表,需要使用者在使用的时候显示地获取和释放锁。
参考
  • https://www.jianshu.com/p/155260c8af6c

重入锁

标签:++   进入   因此   ring   imp   高级功能   shu   cas   关键字   

原文地址:https://www.cnblogs.com/frankltf/p/10345355.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!