聊聊关于Reentrantlock


Reentrantlock—可重入锁,之前我们学过synchronized,这个锁也是可重入的,那么为什么还需要一个专门的可重入锁?这是因为虽然两者都是可重入的,但ReentrantLock相比synchronized功能更加丰富,使用更为灵活,也更适合复杂的并发场景,因此可以用于替代synchronized。

Reentranlock的方法

  • lock():获取锁,不拿到锁誓不罢休
  • tryLock():尝试获取锁,能拿到就拿,拿不到就溜
  • lockInterruptibly():获取锁,线程在请求被阻塞时,可以被interrupt
  • unlock():释放锁,需要手动释放,一般放在finally语句块中

Reentranlock的基础用法

public class ReLockTest1 {
   Lock lock = new ReentrantLock();

   void m1() {
       try {
           lock.lock();
           for (int i = 0; i < 5; i++) {
               TimeUnit.SECONDS.sleep(1);
               System.out.println(i);
           }
       } catch (InterruptedException e) {
           e.printStackTrace();
       } finally {
           lock.unlock();
       }
   }

   void m2() {
       try {
           lock.lock();
           System.out.println("m2...");
       } finally {
           lock.unlock();
       }
   }

   public static void main(String[] args) {
       ReLockTest1 reLock = new ReLockTest1();
       new Thread(reLock::m1, "t1").start();

       try {
           TimeUnit.SECONDS.sleep(1);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       new Thread(reLock::m2, "t2").start();
   }
}

这个程序中,首先,需要new一个Reentranlock对象lock,使用lock去锁住对象,与synchronized作用一样,但是,需要注意这些语句要写在try语句块中,然后在finally中手动释放锁。主程序中,两个线程,分别获取锁,然后执行方法。最后得到的结果: 0 1 2 3 4 m2…

tryLock

其中,Reentranlock更优秀的一点就是可以在一定时间的范围内尝试获取锁,如果过了这个时间没有得到,那也不强求,如下代码:

public class TryLockTest {
    Lock lock = new ReentrantLock();
    boolean isLocked = false;
    void m1() {
        try {
            isLocked = lock.tryLock(3, TimeUnit.SECONDS);  //time可变
            System.out.println("m1..." + isLocked);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(isLocked)
                lock.unlock();
        }
    }

    void m2() {
        try {
            lock.lock();
            for(int i = 0; i < 5; i++) {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(i);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        TryLockTest tryLock = new TryLockTest();
        new Thread(tryLock::m2).start();
        new Thread(tryLock::m1).start();
    }
}

m1方法在3秒内进行tryLock,随后输出语句并判断锁的状态,m2方法lock,并在5秒内的每秒输出数字,main函数中创建两个线程分别调用方法,随后执行。执行结果:如果tryLock秒数小于5,则isLocked状态为false,否则为true。
值得注意的是:tryLock并不是在一开始就开始抢锁的,而是在设置秒数是最大时间出进行时间片的抢夺。

公平不公平?

Reentranlock默认是非公平锁,如果想要成为公平锁,那么在需要new Reentranlock(true),这样传参成为公平锁,如果传参为false或者没有参数则为非公平锁。来段代码,可以看出公不公平的结果体现

public class IsFair implements Runnable {
    Lock lock = new ReentrantLock(/*true*/);


    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                lock.lock();
                System.out.println(Thread.currentThread().getName() + "获得锁");
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        IsFair isFair = new IsFair();
        Thread t1 = new Thread(isFair);
        Thread t2 = new Thread(isFair);
        t1.start();
        t2.start();
    }
}

测试结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值