`
withoutme_hw
  • 浏览: 9643 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

ReentrantLock实现-学习笔记

 
阅读更多

    线程安全往往需要靠互斥锁机制来保证,ReentrantLock是比关键字sychronized更灵活的可重入互斥锁。ReentrantLock在不使用锁(它自己本身就是Lock)和synchronized关键字的前提下,是怎么保证线程安全的呢。

    看一下不公平锁实现的lock方法(调用的是Sync(NonfairSync)的lock方法

    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

    1. 先通过CAS原子操作来试图获取锁(当前状态==0并且成功的将状态改为1),如果CAS返回true,说明成功获取到锁,那么简单的将该锁的拥有线程设为当前线程即可返回。锁获取成功。

    2. 如果CAS返回false,则调用acquire方法,其中先调用tryAcquire方法,在不公平锁的实现中,tryAcuqire方法首先做的操作与lock方法的第一步操作基本重复,也是先通过CAS原子操作尝试获取锁,成功则设置所谓当前线程所有。如果当前的状态不为0(说明有线程已经获取到该锁),则判断持有该锁的是不是当前线程自身,如果是自身,由于是可重入锁,则简单的将当前状态计数+1就可返回,锁获取成功。

        

    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

 

       //tryAcquire 
       /**
         * Performs non-fair tryLock.  tryAcquire is
         * implemented in subclasses, but both need nonfair
         * try for trylock method.
         */
       final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

      3. 如果不是上面这2种情况,则说明锁已经被其他线程排他占用,则调用addWaiter先将当前线程放入等待队列中,然后在acquireQueued方法中,循环判断是否已经轮到当前节点(即该节点前面没有可用节点),如果没有有效节点,则再尝试调用tryAcquire方法,失败则继续循环,否则成功获取到锁并返回。如果前面有其他节点,则将当前线程park,当前线程阻塞,可能直到其他线程unlock调用unpark,然后才恢复执行并重新试图获取该锁。

     //this method is implemented in AbstractQueuedSynchronizer
    /**
     * Acquires in exclusive uninterruptible mode for thread already in
     * queue. Used by condition wait methods as well as acquire.
     *
     * @param node the node
     * @param arg the acquire argument
     * @return {@code true} if interrupted while waiting
     */
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

 

分享到:
评论

相关推荐

    Java并发编程学习笔记

    4、ReentrantLock底层实现和如何使用 5、Condition源码分析 6、ReentrantReadWriteLock底层实现原理 7、并发工具类CountDownLatch 、CyclicBarrier和Semaphore底层实现原理 8、线程池原理和如何使用线程池 9、...

    良葛格 Java 学习笔记-JavaGossip全(v1+v2)

    《良葛格 Java 学习笔记-JavaGossip全(v1+v2)》是一部集成了作者良葛格多年编程经验的学习资料,旨在帮助初学者和有经验的开发者深入理解和掌握Java这门强大的编程语言。这份笔记包含了JavaGossip的两个版本,v1和...

    java基础学习笔记

    本Java基础学习笔记将深入探讨Java的核心概念和技术,帮助初学者建立起坚实的编程基础。 一、Java环境搭建 学习Java首先需要安装Java Development Kit(JDK),这是编写和运行Java程序所需的基本工具集。安装完成后...

    JDK学习笔记的全部

    Java JDK学习笔记全面解析 Java Development Kit(JDK)是Java编程语言的核心组成部分,它包含了开发和运行Java应用程序所需的所有工具和库。本篇将深入探讨JDK的内部结构,揭示其背后的秘密。 1. JDK概述 JDK是...

    Java JDK 6学习笔记——ppt

    Java JDK 6学习笔记——PPT简体版是针对初学者和有经验的开发者们的一份宝贵资源,它深入浅出地介绍了Java编程语言的核心概念和技术。这份资料以PPT的形式呈现,使得学习过程更加直观易懂,同时包含了课程中的源代码...

    java从入门到精通学习笔记-Lesson5(多线程).pdf

    此外,Java还提供了多种同步机制来处理多线程间的交互,如`synchronized`关键字实现互斥访问,`wait()`和`notify()`方法实现线程间通信,以及`Lock`接口和`ReentrantLock`类提供更灵活的锁机制。理解并掌握这些机制...

    Java JDK 6学习笔记——ppt简体版

    Java JDK 6学习笔记——PPT简体版是针对初学者和Java爱好者的一份宝贵资料,它涵盖了Java JDK 6的基础知识和核心概念。这份笔记旨在帮助读者掌握Java编程语言的关键点,为深入学习和实际开发奠定基础。下面将详细...

    java中的并发变成学习笔记2

    它使用FIFO(先进先出)队列结构,即`Node`类实现的同步队列和条件队列。 AQS的设计允许子类通过继承并实现其特定的同步行为。主要的方法包括`acquire`和`release`,用于获取和释放同步状态。AQS支持两种模式:独占...

    java多线程学习笔记02(csdn)————程序.pdf

    在这个学习笔记中,主要讨论了Java中的线程同步机制,包括volatile关键字、synchronized以及Lock接口,特别是ReentrantLock的使用。 首先,对于线程1和线程2的疑惑,调试(debug)模式并不能改变线程的执行顺序。...

    core java I (java核心编程)学习笔记

    理解线程同步机制,如synchronized关键字、wait/notify机制,以及Lock接口和ReentrantLock类。 8. **泛型**:泛型引入于Java 5,用于提供类型安全,减少类型转换的麻烦。学习泛型类、泛型方法、通配符和泛型边界。 ...

    多线程学习笔记.docx

    Java提供了多种同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法、ReentrantLock等。synchronized可以修饰方法或代码块,确保同一时间只有一个线程能执行特定代码,避免数据不一致。wait()、...

    JAVA多线程学习笔记整理(csdn)————程序.pdf

    - **Lock对象**:ReentrantLock等锁对象提供了更灵活的控制,支持公平锁和非公平锁,以及可重入性,需要手动调用lock()和unlock()进行锁定和解锁。 5. **线程通信** - **线程间的通信**:可以通过共享变量、wait...

    并发锁核心类AQS学习笔记

    JUC 包中的同步类基本都是基于 AQS 同步器来实现的,如 ReentrantLock,Semaphore 等。 二、原理 1、AQS 工作机制: 如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为...

    java复习笔记

    线程同步机制包括synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口和相关实现类,如ReentrantLock。 八、网络编程 Java提供了丰富的网络编程API,如Socket和ServerSocket用于TCP连接,...

    良葛格 Java 學習筆記-V2.zip

    【Java学习笔记-V2】是良葛格精心整理的一份Java学习资源,旨在帮助初学者和进阶者深入理解Java编程语言。这份笔记涵盖了Java的基础概念、语法特性、面向对象编程、异常处理、多线程、集合框架、IO流、网络编程、...

    JUC个人笔记1

    在Lock接口(这里使用的是ReentrantLock可重入锁)版本中,我们可以手动控制锁的获取和释放,提供了更高的灵活性。`saleTicket()`方法中的`lock.lock()`和`lock.unlock()`确保了对共享资源的独占访问。同时,使用...

    李兴华javase全部笔记.zip

    线程同步和通信是多线程编程的关键,包括synchronized关键字、wait()、notify()和notifyAll()方法以及各种锁(如ReentrantLock)。 7. **网络编程**:Java提供了丰富的Socket类和ServerSocket类,支持TCP/IP协议...

    Java实验9多线程设计.doc

    - **题3**:模拟三个线程(代表老师)分发学习笔记,可以使用synchronized关键字或Lock接口(如ReentrantLock)确保线程安全地分配资源。 8. **实验结果和分析**: 实验的结果将展示线程并发执行的特点,例如线程...

    JAVA解惑.大全和问题解析

    在Java编程语言的学习过程中,经常会遇到各种困惑和问题。"JAVA解惑.大全和问题解析"这个资源就是针对这些问题提供的一份详尽的解答指南。它涵盖了Java的基础知识、常见疑惑点以及易错知识点,旨在帮助Java初学者和...

Global site tag (gtag.js) - Google Analytics