java线程之可重入锁

简介: java线程之可重入锁

一、什么是可重入锁

可重入锁就是可以重复进入的锁,也叫递归锁。前提是同一把锁,如同一个类、同一个实例、同一个代码块。

来自知乎的解释:可重入锁指的是同一个线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。也就是说,线程可以进入任何一个他已经拥有锁的所有同步代码块。


Coffey强的解释:可重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。

synchronized 和 ReentrantLock 都是可重入锁。

可重入锁的意义之一在于防止死锁。synchronized 和 ReentrantLock 都是可重入锁。

二、代码演示

1、synchronized

public static void main(String[] args) {
        Object obj = new Object();
        new Thread(() -> {
            //第一次加锁
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "第一层");
                //第二次加锁,此时obj对象处于锁定状态,但是当前线程仍然可以进入,避免死锁
                synchronized (obj) {
                    int a = 3 / 0;
                    System.out.println(Thread.currentThread().getName() + "第二层");
                }
            }
        }, "t1").start();
        new Thread(() -> {
            //第一次加锁
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + "第一层");
                //第二次加锁,此时obj对象处于锁定状态,但是当前线程仍然可以进入,避免死锁
                synchronized (obj) {
                    System.out.println(Thread.currentThread().getName() + "第二层");
                }
            }
        }, "t2").start();
    }

t1线程第二层有异常,使用synchronized关键字,发生异常,会自动释放锁,t2线程正常输出。

2、lock

 public static void main(String[] args) {
        Lock lock = new ReentrantLock(false);
        new Thread(() -> {
            //第一次加锁
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "第一层");
                //第二次加锁,此时lock处于锁定状态,但是当前线程仍然可以进入,避免死锁
                lock.lock();
                try {
                    int a = 3 / 0;
                    System.out.println(Thread.currentThread().getName() + "第二层");
                } finally {
                    lock.unlock();
                }
            } finally {
                lock.unlock();
            }
 
        }, "t1").start();
        new Thread(() -> {
            //第一次加锁
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "第一层");
                //第二次加锁,此时lock处于锁定状态,但是当前线程仍然可以进入,避免死锁
                lock.lock();
                try {
                    //int a=3/0;
                    System.out.println(Thread.currentThread().getName() + "第二层");
                } finally {
                    lock.unlock();
                }
            } finally {
                lock.unlock();
            }
        }, "t2").start();
    }

t1线程第二层有异常,我们的释放锁写在finally里边,不影响t2线程正常输出。

源码推荐的写法

三、Lock和Synchronized的异同

目录
相关文章
|
16小时前
|
Java 数据处理 调度
Java多线程编程入门指南
Java多线程编程入门指南
|
22小时前
|
设计模式 算法 Java
简单了解下Java中锁的概念和原理
Java的锁通过java代码实现,go语言的锁通过go实现,python语言的锁通过python实现。它们都实现的什么呢?这部分就是锁的定义和设计模式、算法、原理等一些理论上的东西。
9 1
|
1天前
|
监控 安全 算法
如何有效地处理Java中的多线程
如何有效地处理Java中的多线程
|
2天前
|
Java 调度
Java多线程编程与并发控制策略
Java多线程编程与并发控制策略
|
2天前
|
安全 算法 Java
java多线程面试题2019整理
java多线程面试题2019整理
|
2天前
|
安全 Java 开发者
Java并发编程:理解并发与多线程
在当今软件开发领域,Java作为一种广泛应用的编程语言,其并发编程能力显得尤为重要。本文将深入探讨Java中的并发编程概念,包括多线程基础、线程安全、并发工具类等内容,帮助开发者更好地理解和应用Java中的并发特性。
6 1
|
2天前
|
存储 安全 算法
深入探索Java中的MarkWord与锁优化机制——无锁、偏向锁、自旋锁、重量级锁
深入探索Java中的MarkWord与锁优化机制——无锁、偏向锁、自旋锁、重量级锁
7 1
|
3天前
|
监控 Java 调度
Java并发编程:深入理解线程池
【6月更文挑战第26天】在Java并发编程的世界中,线程池是提升应用性能、优化资源管理的关键组件。本文将深入探讨线程池的内部机制,从核心概念到实际应用,揭示如何有效利用线程池来处理并发任务,同时避免常见的陷阱和错误实践。通过实例分析,我们将了解线程池配置的策略和对性能的影响,以及如何监控和维护线程池的健康状况。
7 1
|
19小时前
|
安全 Java 开发者
Java并发编程中的线程安全策略
在现代软件开发中,Java语言的并发编程特性使得多线程应用成为可能。然而,随着线程数量的增加,如何确保数据的一致性和系统的稳定性成为开发者面临的挑战。本文将探讨Java并发编程中实现线程安全的几种策略,包括同步机制、volatile关键字的使用、以及java.util.concurrent包提供的工具类,旨在为Java开发者提供一系列实用的方法来应对并发问题。
7 0
|
21小时前
|
监控 Java UED
Java并发编程:深入理解线程池的设计与应用
本文旨在通过数据导向和科学严谨的方式,深入探讨Java并发编程中的关键组件——线程池。文章首先概述了线程池的基本概念与重要性,随后详细解读了线程池的核心参数及其对性能的影响,并通过实验数据支持分析结果。此外,文中还将介绍如何根据不同的应用场景选择或设计合适的线程池,以及如何避免常见的并发问题。最后,通过案例研究,展示线程池在实际应用中的优化效果,为开发人员提供实践指导。
7 0