线程的基本方法-重入锁ReentrantLock(一)

本文介绍了ReentrantLock的基本用法及特点,并与synchronized进行了对比。包括可重入性、公平锁选择、中断响应、限时等待等方面的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  说到ReentrantLock,肯定要提一下synchronized,两者都是解决并发的重要工具。在jdk5的版本,重入锁的性能是好于synchronized,但是从6开始,jdk对synchronized做了很多的优化,目前两者性能相差不大,官方建议synchronized的方式。

说一下两者的相同点和不同点:

相同点:

(1)都是可重入锁,同一个线程每进入一次,锁的计数器都自增1,等到锁的计数器值降为0时才会释放锁。

不同点:

(1)使用方式不同,synchronized依赖于JVM实现的,而ReentrantLock是JDK实现的。synchronized由编译器去保证锁的加锁和释放,而ReentrantLock使用起来相当灵活,需要手动添加lock和unlock方法。

(2) ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。

(3)ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。

(4) ReenTrantLock是可中断锁,通过lock.lockInterruptibly()来实现。

1.ReentrantLock基本用法

class ReenterLock implements Runnable{
    public  static ReentrantLock reentrantLock=new ReentrantLock();
    public static  int i=0;
    @Override
    public void run(){
       for(int j=0;j<1000;j++){
           reentrantLock.lock();
           //reentrantLock.lock();
           try{
               i++;
           }finally {
               reentrantLock.unlock();
              //reentrantLock.unlock();
           }
       }

    }
    public static void main(String[] args) throws InterruptedException {
        ReenterLock reenterLock=new ReenterLock();
        Thread t1=new Thread(reenterLock);
        Thread t2=new Thread(reenterLock);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("i:"+i);
    }
}

  生成两个线程,让主线程等待两个线程执行完毕,t1和t2相当于并行。手动加锁和释放锁,lock和unlock次数要保持一致,因为ReentrantLock持有一个所计数器,当已持有锁的线程再次获得该锁时计数器值加1,每调用一次lock.unlock()时所计数器值减一,直到所计数器值为0,此时线程释放锁。

2.中断响应

  ReenTrantLock是可中断锁,通过lock.lockInterruptibly()来实现。此方法也是加锁的动作,只是可以对中断产生响应 :


class ReenterLock implements Runnable{
    public  static ReentrantLock reentrantLock=new ReentrantLock();
    public  static ReentrantLock reentrantLock2=new ReentrantLock();
    int flag;
    public static  int i=0;
    ReenterLock(int flag){
        this.flag=flag;
    }
    @Override
    public void run(){
        try{
            if(flag==1){
                reentrantLock.lockInterruptibly();
                try{
                    Thread.sleep(500);
                    System.out.println("11");
                }catch (Exception e){
                    e.printStackTrace();
                }
                reentrantLock2.lockInterruptibly();
            }else{
                reentrantLock2.lockInterruptibly();
                try{
                    Thread.sleep(500);
                    System.out.println("22");
                }catch (Exception e){
                    e.printStackTrace();
                }
                reentrantLock.lockInterruptibly();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(reentrantLock.isHeldByCurrentThread()){
                reentrantLock.unlock();
            }
            if(reentrantLock2.isHeldByCurrentThread()){
                reentrantLock2.unlock();
            }
            System.out.println(Thread.currentThread().getId()+":线程退出");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        ReenterLock reenterLock=new ReenterLock(1);
        ReenterLock reenterLock2=new ReenterLock(2);
        Thread t1=new Thread(reenterLock);
        Thread t2=new Thread(reenterLock2);
        t1.start();
        t2.start();
        //t1.join();
        //t2.join();
        Thread.sleep(1000);
        t1.interrupt();
        System.out.println("i:"+i);
    }

  启动t1和t2之后,两个线程会互相等待,形成死锁。这时候主动中断t1线程,t1放弃任务退出,t2获取锁完成任务退出。

3.锁申请等待限时

  用tryLock实现限时等待,超出时间还没有得到锁的时候,放弃等待:

class TimerLock implements Runnable{
    public  static ReentrantLock reentrantLock=new ReentrantLock();
    int flag;
    public static  int i=0;
    @Override
    public void run(){
        try{
            if (reentrantLock.tryLock(5, TimeUnit.SECONDS)) {
                System.out.println(Thread.currentThread().getId());
                Thread.sleep(6000);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(reentrantLock.isHeldByCurrentThread()){
                reentrantLock.unlock();
            }
            System.out.println(Thread.currentThread().getId()+":线程退出");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        TimerLock reenterLock=new TimerLock();
        Thread t1=new Thread(reenterLock);
        Thread t2=new Thread(reenterLock);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("i:"+i);
    }
}

 tryLock()会返回值,true代表成功获取到锁,false代表获取锁失败。不带时间参数的时候,会直接返回true或false。这样返回参数之后就可以通过返回值来控制等待与否,从而有效的避免死锁:

  

class ReenterLock implements Runnable{
    public  static ReentrantLock reentrantLock=new ReentrantLock();
    public  static ReentrantLock reentrantLock2=new ReentrantLock();
    int flag;
    public static  int i=0;
    ReenterLock(int flag){
        this.flag=flag;
    }
    @Override
    public void run(){
        try{
            if(flag==1){
                //用while来不停的获取锁的状态,尝试加锁
                while (true) {
                    if (reentrantLock.tryLock()) {
                        try {
                            Thread.sleep(500);
                            System.out.println("11");
                            // 尝试获取第二个锁
                            if (reentrantLock2.tryLock()) {
                                try {
                                    Thread.sleep(500);
                                    System.out.println("2222");
                                    return;
                                }finally {
                                    reentrantLock2.unlock();
                                }
                            }
                        }finally {
                            System.out.println("-----");
                            reentrantLock.unlock();
                        }
                    }
                }

            }else{
                //用while来不停的获取锁的状态,尝试加锁
                while (true) {
                    if (reentrantLock2.tryLock()) {
                        try {
                            Thread.sleep(500);
                            System.out.println("33");
                            // 尝试获取第二个锁
                            if (reentrantLock.tryLock()) {
                                try {
                                    Thread.sleep(500);
                                    System.out.println("44");
                                    return;
                                }finally {
                                    reentrantLock.unlock();
                                }
                            }
                        }finally {
                            System.out.println("-----");
                            reentrantLock2.unlock();
                        }
                    }
                }

            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println(Thread.currentThread().getId()+":线程退出");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        ReenterLock reenterLock=new ReenterLock(1);
        ReenterLock reenterLock2=new ReenterLock(2);
        Thread t1=new Thread(reenterLock);
        Thread t2=new Thread(reenterLock2);
        t1.start();
        t2.start();
        //t1.join();
        //t2.join();
        //Thread.sleep(1000);
        //t1.interrupt();
        System.out.println("i:"+i);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值