线程安全往往需要靠互斥锁机制来保证,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); } }
相关推荐
4、ReentrantLock底层实现和如何使用 5、Condition源码分析 6、ReentrantReadWriteLock底层实现原理 7、并发工具类CountDownLatch 、CyclicBarrier和Semaphore底层实现原理 8、线程池原理和如何使用线程池 9、...
《良葛格 Java 学习笔记-JavaGossip全(v1+v2)》是一部集成了作者良葛格多年编程经验的学习资料,旨在帮助初学者和有经验的开发者深入理解和掌握Java这门强大的编程语言。这份笔记包含了JavaGossip的两个版本,v1和...
本Java基础学习笔记将深入探讨Java的核心概念和技术,帮助初学者建立起坚实的编程基础。 一、Java环境搭建 学习Java首先需要安装Java Development Kit(JDK),这是编写和运行Java程序所需的基本工具集。安装完成后...
Java JDK学习笔记全面解析 Java Development Kit(JDK)是Java编程语言的核心组成部分,它包含了开发和运行Java应用程序所需的所有工具和库。本篇将深入探讨JDK的内部结构,揭示其背后的秘密。 1. JDK概述 JDK是...
Java JDK 6学习笔记——PPT简体版是针对初学者和有经验的开发者们的一份宝贵资源,它深入浅出地介绍了Java编程语言的核心概念和技术。这份资料以PPT的形式呈现,使得学习过程更加直观易懂,同时包含了课程中的源代码...
此外,Java还提供了多种同步机制来处理多线程间的交互,如`synchronized`关键字实现互斥访问,`wait()`和`notify()`方法实现线程间通信,以及`Lock`接口和`ReentrantLock`类提供更灵活的锁机制。理解并掌握这些机制...
Java JDK 6学习笔记——PPT简体版是针对初学者和Java爱好者的一份宝贵资料,它涵盖了Java JDK 6的基础知识和核心概念。这份笔记旨在帮助读者掌握Java编程语言的关键点,为深入学习和实际开发奠定基础。下面将详细...
它使用FIFO(先进先出)队列结构,即`Node`类实现的同步队列和条件队列。 AQS的设计允许子类通过继承并实现其特定的同步行为。主要的方法包括`acquire`和`release`,用于获取和释放同步状态。AQS支持两种模式:独占...
在这个学习笔记中,主要讨论了Java中的线程同步机制,包括volatile关键字、synchronized以及Lock接口,特别是ReentrantLock的使用。 首先,对于线程1和线程2的疑惑,调试(debug)模式并不能改变线程的执行顺序。...
理解线程同步机制,如synchronized关键字、wait/notify机制,以及Lock接口和ReentrantLock类。 8. **泛型**:泛型引入于Java 5,用于提供类型安全,减少类型转换的麻烦。学习泛型类、泛型方法、通配符和泛型边界。 ...
Java提供了多种同步机制,如synchronized关键字、wait()、notify()和notifyAll()方法、ReentrantLock等。synchronized可以修饰方法或代码块,确保同一时间只有一个线程能执行特定代码,避免数据不一致。wait()、...
- **Lock对象**:ReentrantLock等锁对象提供了更灵活的控制,支持公平锁和非公平锁,以及可重入性,需要手动调用lock()和unlock()进行锁定和解锁。 5. **线程通信** - **线程间的通信**:可以通过共享变量、wait...
JUC 包中的同步类基本都是基于 AQS 同步器来实现的,如 ReentrantLock,Semaphore 等。 二、原理 1、AQS 工作机制: 如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为...
线程同步机制包括synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口和相关实现类,如ReentrantLock。 八、网络编程 Java提供了丰富的网络编程API,如Socket和ServerSocket用于TCP连接,...
【Java学习笔记-V2】是良葛格精心整理的一份Java学习资源,旨在帮助初学者和进阶者深入理解Java编程语言。这份笔记涵盖了Java的基础概念、语法特性、面向对象编程、异常处理、多线程、集合框架、IO流、网络编程、...
在Lock接口(这里使用的是ReentrantLock可重入锁)版本中,我们可以手动控制锁的获取和释放,提供了更高的灵活性。`saleTicket()`方法中的`lock.lock()`和`lock.unlock()`确保了对共享资源的独占访问。同时,使用...
线程同步和通信是多线程编程的关键,包括synchronized关键字、wait()、notify()和notifyAll()方法以及各种锁(如ReentrantLock)。 7. **网络编程**:Java提供了丰富的Socket类和ServerSocket类,支持TCP/IP协议...
- **题3**:模拟三个线程(代表老师)分发学习笔记,可以使用synchronized关键字或Lock接口(如ReentrantLock)确保线程安全地分配资源。 8. **实验结果和分析**: 实验的结果将展示线程并发执行的特点,例如线程...
在Java编程语言的学习过程中,经常会遇到各种困惑和问题。"JAVA解惑.大全和问题解析"这个资源就是针对这些问题提供的一份详尽的解答指南。它涵盖了Java的基础知识、常见疑惑点以及易错知识点,旨在帮助Java初学者和...