Java Lock 之 lock,tryLock 和 lockInterruptibly

lock,tryLock 和 lockInterruptibly 是 Java ReentrantLock 对象提供的三种获取锁的方式。
某个线程调用ReentrantLock 对象的 lock 方法后,如果锁尚未被其它线程占有,则该线程将获得锁;如果锁已经被其它线程占有,则该线程将一直 block 直到它成功获得锁。block 过程中不响应中断,获得锁后才根据中断状态进行相应处理。
某个线程调用ReentrantLock 对象的 lockInterruptibly 方法后,如果锁尚未被其它线程占有,则该线程将获得锁;如果锁已经被其它线程占有,则该线程将一直 block 直到它成功获得锁或者该线程被中断。block 过程中发生线程中断时,该线程退出锁的竞争,抛出 InterruptedException 异常。

import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Lock 的 lock() 方法和 lockInterruptibly() 方法的差异测试
 */
public class LockInterruptiblyTest {
    /**
     * 在 lockNoInterrupt 上使用 lock() 方法
     */
    ReentrantLock lockNoInterrupt = new ReentrantLock();
    public void noInterruptLock(){
        Runnable noInterruptLock = () -> {
            lockNoInterrupt.lock();
            try{
                System.out.println(String.format("%s %s locked", new Date(System.currentTimeMillis()), Thread.currentThread().getName()));
            }finally{
                //这里不释放锁,测试锁竞争者如何处理中断
                //lockNoInterrupt.unlock();
            }
        };
        //lockNoInterrupt 将被下面的两个线程竞争
        Thread noInterruptThread1 = new Thread(noInterruptLock, "No Interrupt Thread 1");
        Thread noInterruptThread2 = new Thread(noInterruptLock, "No Interrupt Thread 2");
        //No Interrupt Thread 1 获取锁,并且不释放
        noInterruptThread1.start();
        try{
            TimeUnit.MILLISECONDS.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //No Interrupt Thread 2 尝试获取锁,会被 block
        noInterruptThread2.start();
        try{
            TimeUnit.MILLISECONDS.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //No Interrupt Thread 2 无法得到锁,尝试中断,但中断不会被线程响应
        noInterruptThread2.interrupt();
    }

    /**
     * 在 lockInterrupt 上使用 lockInterruptibly() 方法
     */
    ReentrantLock lockInterrupt = new ReentrantLock();
    public void lockInterrupt(){
        //测试 lockInterruptibly() 方法
        Runnable interruptLock = () -> {
            try{
                lockInterrupt.lockInterruptibly();
                System.out.println(String.format("%s %s locked", new Date(System.currentTimeMillis()), Thread.currentThread().getName()));
            }catch (InterruptedException e) {
                System.out.println(String.format("%s %s interrupted", new Date(System.currentTimeMillis()), Thread.currentThread().getName()));
            }finally{
                //这里不释放锁,测试锁竞争者如何处理中断
                //lockInterrupt.unlock();
            }
        };
        //lockInterrupt 将被下面的两个线程竞争
        Thread interruptThread1 = new Thread(interruptLock, "Interrupt Thread 1");
        Thread interruptThread2 = new Thread(interruptLock, "Interrupt Thread 2");
        //Interrupt Thread 1 获取锁,并且不释放
        interruptThread1.start();
        try{
            TimeUnit.MILLISECONDS.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //Interrupt Thread 2 尝试获取锁,会被 block
        interruptThread2.start();
        try{
            TimeUnit.MILLISECONDS.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //Interrupt Thread 2 无法得到锁,尝试中断,线程中断后结束
        interruptThread2.interrupt();
    }

    public static void main(String[] args){
        LockInterruptiblyTest test = new LockInterruptiblyTest();
        test.noInterruptLock();
        test.lockInterrupt();
    }
}
/* output
Tue Dec 04 18:45:30 CST 2018 No Interrupt Thread 1 locked
Tue Dec 04 18:45:32 CST 2018 Interrupt Thread 1 locked
Tue Dec 04 18:45:34 CST 2018 Interrupt Thread 2 interrupted
...
 */

我们发现 No Interrupt Thread 1 和 No Interrupt Thread 2 使用了 lock 方法,由于 No Interrupt Thread 1 一直占有锁,No Interrupt Thread 2 在尝试获得锁后会一直 block,即使尝试中断它,No Interrupt Thread 2 线程仍保持 wait 锁的状态,程序无法结束。
而 Interrupt Thread 1 和 Interrupt Thread 2 使用了 lockInterruptibly 方法,由于 Interrupt Thread 1 一直占有锁,Interrupt Thread 2 在尝试获得锁后会一直 block,但我们尝试中断它,Interrupt Thread 2 线程就会停止 wait 锁,处理中断请求,进而线程结束。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值