并发编程-concurrent指南-Lock-可重入锁(ReentrantLock)

可重入和不可重入的概念是这样的:当一个线程获得了当前实例的锁,并进入方法A,这个线程在没有释放这把锁的时候,能否再次进入方法A呢?

  • 可重入锁:可以再次进入方法A,就是说在释放锁前此线程可以再次进入方法A(方法A递归)。
  • 不可重入锁(自旋锁):不可以再次进入方法A,也就是说获得锁进入方法A是此线程在释放锁钱唯一的一次进入方法A。

,具体区别查看可重入锁和不可重入锁区别

ReentrantLock,意思是“可重入锁”。ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法。下面通过一些实例看具体看一下如何使用ReentrantLock。

lock()的正确使用方法

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MainLock {
    private Lock lock = new ReentrantLock();
    public static void main(String[] args) {
        final MainLock mainLock = new MainLock();

        new Thread(new Runnable() {
            @Override
            public void run() {
                mainLock.insert(Thread.currentThread());
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                mainLock.insert(Thread.currentThread());
            }
        }).start();
    }

    public void insert(Thread thread){
        lock.lock();//获取锁
        try{
            System.out.println(thread.getName() + "获取锁");
            for(int i=0;i<5;i++){
                System.out.println("------------------------" + thread.getName() + ":"+i+"------------------------");
            }
        }finally {
            System.out.println(thread.getName() + "释放锁");
            lock.unlock();//释放锁
        }
    }
}

结果:

Thread-0获取锁
------------------------Thread-0:0------------------------
------------------------Thread-0:1------------------------
------------------------Thread-0:2------------------------
------------------------Thread-0:3------------------------
------------------------Thread-0:4------------------------
Thread-0释放锁
Thread-1获取锁
------------------------Thread-1:0------------------------
------------------------Thread-1:1------------------------
------------------------Thread-1:2------------------------
------------------------Thread-1:3------------------------
------------------------Thread-1:4------------------------
Thread-1释放锁

tryLock()的使用方法

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MainTryLock {
    private Lock lock = new ReentrantLock();
    public static void main(String[] args) {
        final MainTryLock mainTryLock = new MainTryLock();

        new Thread(){
            @Override
            public void run() {
                mainTryLock.insert(Thread.currentThread());
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                mainTryLock.insert(Thread.currentThread());
            }
        }.start();
    }

    public void insert(Thread thread){
        if(lock.tryLock()){
            try{
                System.out.println(thread.getName() + "获取锁");
                for(int i=0;i<5;i++){
                    Thread.sleep(200);
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                System.out.println(thread.getName() + "释放锁");
                lock.unlock();//释放锁
            }
        }else{
            System.out.println(thread.getName()+"未获取到锁");
        }
    }
}

结果:

Thread-0获取锁
Thread-1未获取到锁
Thread-0释放锁

lockInterruptibly()响应中断的使用方法:

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

public class MainLockInterruptibl {
    private  Lock lock = new ReentrantLock();
    public static void main(String[] args)  {
        MainLockInterruptibl test = new MainLockInterruptibl();
        MyThread thread1 = new MyThread(test);
        MyThread thread2 = new MyThread(test);
        thread1.start();
        thread2.start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread2.interrupt();
    }

    public void insert(Thread thread) throws InterruptedException{
        lock.lockInterruptibly();   //注意,如果需要正确中断等待锁的线程,必须将获取锁放在外面,然后将InterruptedException抛出
        try {
            System.out.println(thread.getName()+"得到了锁");
            long startTime = System.currentTimeMillis();
            for( int i=0;i<5;i++) {
                TimeUnit.SECONDS.sleep(2);
            }
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println(Thread.currentThread().getName()+"执行finally");
            lock.unlock();
            System.out.println(thread.getName()+"释放了锁");
        }
    }
    static class MyThread extends Thread {
        private MainLockInterruptibl test = null;
        public MyThread(MainLockInterruptibl test) {
            this.test = test;
        }
        @Override
        public void run() {
            try {
                test.insert(Thread.currentThread());
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println(Thread.currentThread().getName()+"被中断");
            }
        }
    }
}

结果:

Thread-0得到了锁
java.lang.InterruptedException
Thread-1被中断
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
    at com.concurrent.MainLockInterruptibl.insert(MainLockInterruptibl.java:25)
    at com.concurrent.MainLockInterruptibl$MyThread.run(MainLockInterruptibl.java:48)
Thread-0执行finally
Thread-0释放了锁

源码地址:https://github.com/qjm201000/concurrent_reentrantLock.git

原文地址:https://www.cnblogs.com/qjm201000/p/10175489.html

时间: 2024-11-05 16:09:34

并发编程-concurrent指南-Lock-可重入锁(ReentrantLock)的相关文章

Java并发程序设计(12)并发锁之可重入锁ReentrantLock

1.1. 可重入锁ReentrantLock ReentrantLock是java并发库中提供的可重入锁.与synchronized同步块相比,有相似也有不同.相似的地方有: (1)都可以实现多线程之间的同步,避免对共享资源的访问冲突. (2)都是可重入的,即一个已经获取锁的线程可以再次获得同一个锁,synchronized也类似. 不同的地方有: (1)ReentrantLock更灵活,获取锁和释放锁可以在同一个方法中,也可以在不同方法中.synchronized通常用在同一个方法体内. (2

Java并发(九):重入锁 ReentrantLock

一.ReentrantLock类结构 public class ReentrantLock implements Lock, java.io.Serializable { private final Sync sync; // 锁 大部分功能都是委托给Sync来实现的 abstract static class Sync extends AbstractQueuedSynchronizer {} static final class FairSync extends Sync {} static

JAVA多线程重入锁ReentrantLock应用

package concurrent; import java.util.concurrent.*; import java.util.concurrent.locks.ReentrantLock; /** * @Auther:zhl * @Date:2019/7/13 * @Description: 并发测试,重入锁ReentrantLock解决并发问题 */ public class ConcurrentSample { //并发线程数量 private static int users =

Java 重入锁 ReentrantLock 原理分析

1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生.ReentrantLock 的主要功能和 synchronized 关键字一致,均是用于多线程的同步.但除此之外,ReentrantLock 在功能上比 synchronized 更为丰富.比如 ReentrantLock 在加锁期间,可响应中断,可设置超时等. ReentrantLock 是我们

重入锁 ReentrantLock (转)(学习记录)

重入锁(ReentrantLock)是一种递归无阻塞的同步机制.以前一直认为它是synchronized的简单替代,而且实现机制也不相差太远.不过最近实践过程中发现它们之间还是有着天壤之别. 以下是官方说明:一个可重入的互斥锁定 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大.ReentrantLock 将由最近成功获得锁定,并且还没有释放该锁定的线程所拥有.当锁定没有被另一个线程所拥有时,调用 lock 的线程将成功获取

java多线程---重入锁ReentrantLock

1.定义 重入锁ReentrantLock,支持重入的锁,表示一个线程对资源的重复加锁. 2.底层实现 每个锁关联一个线程持有者和计数器,当计数器为0时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法:成功后,JVM会记下锁的持有线程,并且将计数器置为1:此时其它线程请求该锁,则必须等待:而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增:当线程退出同步代码块时,计数器会递减,如果计数器为0,则释放该锁. 3.使用样例 eg: import java

经典笔试题:线程通信(使用重入锁(ReentrantLock)和条件队列(Condition)实现线程间通信)

经典笔试题: 1.自定义容器,提供新增元素(add)和获取元素数量(size)方法.2.启动两个线程.线程1向容器中新增10个数据.线程2监听容器元素数量,当容器元素数量为5时,线程2输出信息并终止. package com.gaopeng.programming.test2; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.conc

java 可重入锁ReentrantLock的介绍

一个小例子帮助理解 话说从前有一个村子,在这个村子中有一口水井,家家户户都需要到这口井里打水喝.由于井水有限,大家只能依次打水.为了实现家家有水喝,户户有水用的目标,村长绞尽脑汁,最终想出了一个比较合理的方案. 首先,在水井边上安排一个看井人,负责维持秩序. 然后,打水时,以家庭为单位,哪个家庭任何人先到井边,就可以先打水,而且如果一个家庭占到了打水权,其家人这时候过来打水不用排队.而那些没有抢占到打水权的人,一个一个挨着在井边排成一队,先到的排在前面. 最后,打水的人打完水以后就告诉看井人,看

【死磕Java并发】-----J.U.C之重入锁:ReentrantLock

此篇博客所有源码均来自JDK 1.8 ReentrantLock,可重入锁,是一种递归无阻塞的同步机制.它可以等同于synchronized的使用,但是ReentrantLock提供了比synchronized更强大.灵活的锁机制,可以减少死锁发生的概率. API介绍如下: 一个可重入的互斥锁定 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大.ReentrantLock 将由最近成功获得锁定,并且还没有释放该锁定的线程所拥