`

可重入锁/不可重入锁

    博客分类:
  • Lock
 
阅读更多

原创转载请注明出处:https://agilestyle.iteye.com/blog/2443634

 

可重入锁

可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提是同一个对象或者类)

Note:

ReentrantLock和synchronized都是可重入锁

public class TestLock {
    public synchronized void test1() throws InterruptedException {
        Thread.sleep(1000);
        System.out.println("test1 invoked...");
        test2();
    }

    public synchronized void test2() throws InterruptedException {
        Thread.sleep(1000);
        System.out.println("test2 invoked...");
    }

    public static void main(String[] args) throws InterruptedException {
        TestLock testLock = new TestLock();
        testLock.test1();
    }
}

上面的代码就是一个可重入锁的一个特点,如果不是可重入锁的话,test2可能不会被当前线程执行,可能造成死锁。 

 

不可重入锁

不可重入锁,与可重入锁相反,不可递归调用,递归调用就会发生死锁。

使用自旋锁来模拟一个不可重入锁

import java.util.concurrent.atomic.AtomicReference;

public class UnreentrantLockTest {
    private static UnreentrantLock lock = new UnreentrantLock();

    public static void main(String[] args) {
        lock.lock();

        test();

        lock.unlock();
    }

    private static void test() {
        lock.lock();

        System.out.println("test invoked...");

        lock.unlock();
    }

    private static class UnreentrantLock {
        private AtomicReference<Thread> owner = new AtomicReference<>();

        public void lock() {
            Thread currentThread = Thread.currentThread();

            for (; ; ) {
                System.out.println(owner);
                if (owner.compareAndSet(null, currentThread)) {
                    System.out.println(currentThread + " locked...");
                    return;
                }
            }
        }

        public void unlock() {
            Thread currentThread = Thread.currentThread();

            owner.compareAndSet(currentThread, null);

            System.out.println(currentThread + " unlock...");
        }
    }
}

Note:

使用原子引用来存放线程,同一个线程两次调用lock()方法,如果不执行unlock()释放锁的话,第二次调用自旋的时候就会产生死锁,这个锁是不可重入的

 

修改上述代码,将它改造成可重入锁,在执行每次操作之前,判断当前锁持有者是否是当前对象,采用state计数

import java.util.concurrent.atomic.AtomicReference;

public class ReentrantLockTest {
    private static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        lock.lock();

        test();

        lock.unlock();
    }

    private static void test() {
        lock.lock();

        System.out.println("test invoked...");

        test1();

        lock.unlock();
    }

    private static void test1() {
        lock.lock();

        System.out.println("test2 invoked...");

        lock.unlock();
    }

    private static class ReentrantLock {
        private AtomicReference<Thread> owner = new AtomicReference<>();
        private int state = 0;

        public void lock() {
            Thread currentThread = Thread.currentThread();

            if (currentThread == owner.get()) {
                state++;
                return;
            }

            for (; ; ) {
                System.out.println(owner);
                if (!owner.compareAndSet(null, currentThread)) {
                    return;
                }
            }
        }

        public void unlock() {
            Thread currentThread = Thread.currentThread();

            if (currentThread == owner.get()) {
                if (state != 0) {
                    state--;
                } else {
                    owner.compareAndSet(currentThread, null);
                }
            }
        }
    }
}

 

 

 

 

 

分享到:
评论

相关推荐

    手写可重入锁

    可重入锁,也称为递归锁,是Java并发编程中的一个重要概念,主要在`java.util.concurrent.locks.ReentrantLock`类中实现。这个概念对于理解多线程环境下的同步控制至关重要,尤其对于初学者来说,掌握其原理和用法...

    自己动手写一把可重入锁测试案例

    总之,可重入锁是Java并发编程中不可或缺的一部分,理解和实现它有助于深入掌握线程安全的概念和机制。通过动手实践,不仅能提升我们的编程技能,还能帮助我们在实际项目中更好地运用这些知识。

    Java 中15种锁的介绍

    2. **可重入锁 / 不可重入锁** - **可重入锁** 允许同一个线程多次进入同一锁定区域,不会导致死锁。Java的`ReentrantLock`和`synchronized`都是可重入锁。 - **不可重入锁** 如果线程已经在持有锁的情况下尝试...

    redislock-基于redis的分布式可重入锁

    分布式可重入锁是分布式系统中解决并发控制和同步问题的关键技术之一,特别是在微服务架构中,多个服务可能需要共享同一资源,此时就需要一种机制来确保数据的一致性和正确性。Redis,作为一个高性能的键值存储系统...

    可重入函数与不可重入函数

    下面将详细介绍可重入函数与不可重入函数的概念、特性以及如何编写和转换这两种类型的函数。 可重入函数是指可以在任何时候中断执行的函数,即使在函数执行过程中,系统切换到另一个任务或中断服务例程执行其他代码...

    Java可重入锁的实现原理与应用场景

    Java可重入锁的实现原理与应用场景 Java可重入锁是一种特殊的锁机制,允许同一个线程在不同的层次上获取同一个锁,而不会发生死锁或阻塞的情况。这种锁机制广泛应用于多线程编程中,用于解决线程之间的同步问题。 ...

    各种锁汇总,乐观锁、悲观锁、分布式锁、可重入锁、互斥锁、读写锁、分段锁、类锁、行级锁等

    本文将深入探讨标题和描述中提及的各种锁,包括乐观锁、悲观锁、分布式锁、可重入锁、互斥锁、读写锁、分段锁、类锁以及行级锁。 1. **乐观锁**:乐观锁假设多线程环境中的冲突较少,所以在读取数据时不加锁,只有...

    Zookeeper 分布式重入排它锁实现

    4. **可重入性实现**:在服务类中,为每个线程维护一个计数器,每次获取锁时计数器加一,释放锁时减一,只有当计数器为零时,才真正删除Zookeeper中的节点。 5. **异常处理**:在实现过程中,要注意处理可能发生的...

    可重入函数

    ### 可重入函数详解 #### 一、可重入函数定义及特点 **1.1 什么是可重入性?** 可重入性是指一个函数可以被多个任务或线程同时调用而不会出现数据错误的情况。这种特性对于多线程编程尤为重要,因为它能够保证在...

    LabVIEW中可重入VI设置范例

    在传统的非可重入VI中,当一个VI正在执行时,如果其他线程试图再次调用该VI,LabVIEW会阻止这个操作,因为担心数据可能会被不一致地修改。而可重入VI允许多个线程同时访问同一VI的实例,每个线程都有自己的数据副本...

    可重入详解可重入详解

    可重入函数应当避免使用这样的锁机制。 5. **不调用不可重入的函数**:如果一个函数调用了另一个不可重入的函数,那么它自身也不再是可重入的。 #### 三、示例分析 以下是一段示例代码,用于说明非可重入与可重...

    java代码-证明synchronized可重入锁

    例如,一个线程在执行递归函数时,每次进入函数都需要获得锁,如果锁不可重入,那么递归调用将无法进行,程序将陷入死锁。 在`README.txt`文件中,可能会包含对这段代码的解释和运行结果的描述。它可能会指出,当...

    Go《Redis实现智能门锁(互斥锁、看门狗、读写锁、红锁、闭锁、可重入锁)》+源代码+设计资料

    Redis实现互斥锁、看门狗、读写锁、红锁、闭锁、可重入锁 - 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载...

    Java源码解析之可重入锁ReentrantLock

    Java源码解析之可重入锁ReentrantLock ReentrantLock是一个可重入锁,在ConcurrentHashMap中使用了ReentrantLock。它是一个可重入的排他锁,它和synchronized的方法和代码有着相同的行为和语义,但有更多的功能。 ...

    Java多线程高并发篇(一)--重入锁

    在Java多线程高并发编程中,重入锁(ReentrantLock)是一个至关重要的概念,它提供了比Java内置锁(synchronized)更细粒度的控制,并且具有更高的可读性和可扩展性。本篇文章将深入探讨重入锁的相关知识点。 首先...

    zookeeper分布式锁实例源码

    不可重入锁不允许同一个线程再次获取已持有的锁。在ZooKeeper中,实现不可重入锁通常涉及创建临时顺序节点,并通过比较节点顺序来决定锁的归属。当线程尝试获取锁时,它会创建一个节点,然后检查自己是否是当前最小...

    举例讲解Python中的死锁、可重入锁和互斥锁

    需要注意的是,由于互斥锁不支持重入,因此在一个线程中多次尝试获取同一把锁会导致线程被永久阻塞。 总结起来,Python中的锁机制是处理多线程同步的重要工具。了解死锁的概念以及如何使用可重入锁和互斥锁对于编写...

    redis实现分布式锁,自旋式加锁,lua原子性解锁

    `SETNX`命令用于设置键值,但如果键已经存在,则不执行任何操作,这可以确保锁的互斥性。`SET key value EX timeout NX`则同时设置了超时时间,防止因程序异常导致的死锁。 自旋式加锁是一种常见的分布式锁实现方式...

    简单了解Java中的可重入锁

    如果自旋锁不支持可重入,那么在递归调用中可能会出现死锁。如代码所示的 `SpinLock` 实现,它没有处理可重入的情况,可能导致线程在尝试获取已经被自己持有的锁时无限循环。改进后的 `SpinLock1` 引入了计数器来...

    教你完全理解ReentrantLock重入锁

    ReentrantLock支持重入性,意味着一个线程可以多次进入同一段被该锁保护的代码,只要这个线程还没有释放这个锁。这种特性对于某些复杂并发场景特别有用。 在ReentrantLock中,重入性是通过维护每个锁的同步状态(即...

Global site tag (gtag.js) - Google Analytics