synchronized
- synchronized 是 Java 内建的同步机制,提供了互斥的语义和可见性。
- 当一个线程已经获得某个锁时,试图获取同一个锁的其它线程将只能等待(或阻塞)。
- 用关键字 synchronized 修饰方法等价于将方法体中的内容用 synchronized 语句块包起来。
public class C { private static int s; private int a; public synchronized void setA(int v) { this.a = v; } public void setA2(int v) { synchronized (this) { this.a = v; } } public static synchronized void setS(int v) { s = v; } public static void setS(int v) { synchronized (C.class) { s = v; } } }
ReentrantLock
- ReentrantLock 直译为“再入锁”,语义和 synchronized 类似。
- “再入”是指对 ReentrantLock 的持有是以线程为单位的,而不是基于调用次数。
- 例:StampedLock 不支持“再入”
- 当一个线程试图再次获取它已经获得的某个 ReentrantLock 时,获取操作自动成功
- 这是它内部的同步器类NonfairSync和FairSync实现的,它们都是AbstractQueuedSynchronizer(传说中的AQS)的子类;
- AQS的父类AbstractOwnableSynchronizer(传说中的AQS)则提供了对互斥的支持。它有一个字段保存了当前拥有它的线程对象的引用。
- 与 synchronized 相比,ReentrantLock 更用法更灵活,支持更多自定义操作。
- 可调用 ReentrantLock.lock() 方法获取锁,调用 ReentrantLock.unlock() 方法释放锁。
- 注:如果编码时未处理好释放锁的操作,可能导致程序一直持有某个ReentrantLock,继而引发异常状况。
- 如,未规划好异常处理,导致通过 lock() 方法拿到锁后出现异常并跳过了 unlock() 方法
ReentrantLock lock; ... public void func1() { lock.lock(); doSomethingMayThrowException(); lock.unlock(); } public void func2() { lock.lock(); try { doSomethingMayThrowException(); } finally { lock.unlock(); } }
- 可通过 ReentrantLock 的构造方法指定该锁是公平锁还是非公平锁
- 公平锁可以将锁给等待时间最久的线程,减少个别线程长期等待锁的现象
- 只有当确实需要公平时才使用公平锁;因为它会导致吞吐量下降
- 其构造方法内部会根据参数使用不同的同步器类(Sync)
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
- tryLock(long timeout, TimeUnit unit) 方法可设定获取锁的最长等待时间
- lockInterruptibly() 方法可以在当前线程未处于中断状态时才获取锁
- 如果当前线程处于中断状态,此方法会抛出InterruptedException
- 可通过 ReentrantLock.newCondition() 方法创建多个 Condition 对象(java.util.concurrent.locks),并利用这些 Condition 对象组合适应不同的使用场景
- 通过 Condition 的 await() 和 signal() 等方法就可以方便地实现一些同步需求
- ArrayBlockingQueue就是通过Condition实现了Blocking语义
final ReentrantLock lock; private final Condition notEmpty; // 构造方法 public ArrayBlockingQueue(int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); this.items = new Object[capacity]; lock = new ReentrantLock(fair); // 创建Condition notEmpty = lock.newCondition(); notFull = lock.newCondition(); } // 获取元素 public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == 0) // 如果队列中没有元素,将一直等待 notEmpty.await(); return dequeue(); } finally { lock.unlock(); } } // 添加元素 private void enqueue(E x) { final Object[] items = this.items; items[putIndex] = x; if (++putIndex == items.length) putIndex = 0; count++; // 发布队列非空通知。该操作可让take()方法结束等待 notEmpty.signal(); }
性能
- 在锁竞争较低的场景中 synchronized 的性能可能更好
- 多线程高竞争场景下,ReentrantLock 的性能更好
实际使用时可先侧重设计简单性与代码整洁性,使用 synchronized。
当确定存在性能问题,且经过测试 ReentrantLock 性能更好时再改。
(《解剖一个有缺陷的微基准测试》)
《性能对比》
Peter Lawrey 写道
Conclusion
In general, unless you have measured you system and you know you have a performance issue, you should do what you believe is simplest and clearest and it is likely to performance well.
These results indicate that synchronized is best for a small number of threads accessing a lock (<4) and Lock may be best for a high number of threads accessing the same locks.
In general, unless you have measured you system and you know you have a performance issue, you should do what you believe is simplest and clearest and it is likely to performance well.
These results indicate that synchronized is best for a small number of threads accessing a lock (<4) and Lock may be best for a high number of threads accessing the same locks.
其它TODO
线程安全性
- 线程安全是指,在多线程环境下,共享的、可修改的数据的正确性。
- 为了达到线程安全,需要保证操作的原子性、可见性、有序性。
- 原子性:执行某个操作时,其内部子操作的执行不会被其它线程干扰
- 可以通过同步机制实现。比如,加锁
- 可见性:某个共享数据被一个线程修改后,其它线程线程能立即知道该数据已被修改
- Java的 volatile 关键字可以保证其修饰的字段的可见性。《volatile》
- 有序性:对共享数据的读写指令是按照代码中的写明的顺序执行的,不会被编译器优化等其它操作重排
相关推荐
2. **同步机制**:为了保证多线程环境下的数据一致性,Java提供了多种同步机制,如`synchronized`关键字、`ReentrantLock`等。 3. **线程池**:通过使用线程池可以有效地管理和复用线程资源,避免频繁创建和销毁线程...
根据提供的信息,“Java语言程序设计-进阶篇(原书第8版)”这本书主要针对有一定基础的Java开发者,旨在帮助他们深入理解Java编程的核心概念和技术,并掌握更高级的应用技巧。虽然描述部分没有给出具体内容,但从书名...
2. **线程同步**:为了解决多线程中的数据安全问题,Java提供了多种同步机制,如`synchronized`关键字、`volatile`变量、`Lock`与`Condition`接口、`ReentrantLock`等。这些内容在书中会有详细讲解,包括它们的工作...
Java并发编程涉及线程、锁、并发工具等,如synchronized关键字、ReentrantLock、CountDownLatch、CyclicBarrier等。线程池通过ExecutorService管理线程,提高资源利用率,可以通过ThreadPoolExecutor创建。 ...
### Java进阶知识 #### 1. 异常处理 Java提供了强大的异常处理机制,通过try-catch-finally结构来捕获和处理程序运行时可能发生的错误。 #### 2. 多线程 - **线程概念**:线程是进程中的一个执行单元,是操作系统...
- 线程同步机制包括synchronized关键字、wait()、notify()和notifyAll()方法,以及Lock接口及其实现如ReentrantLock。 8. **反射机制**: - 反射允许在运行时检查类、接口、字段和方法的信息,甚至动态调用方法和...
在Java架构师进阶之路上,需要掌握的核心知识点涵盖了编程基础、集合框架、JVM原理、并发编程、框架原理、微服务架构、网络编程以及分布式系统等多个方面。以下是详细的知识点概述: ### 基础知识 Java基础是架构师...
线程同步是为了避免多线程环境下数据的不一致性,Java提供了多种同步机制,如synchronized关键字、wait()和notify()方法、Lock接口及其实现类如ReentrantLock等。线程通信主要涉及wait、notify和notifyAll方法,用于...
《Core Java.JAVA核心技术(中文版)》是学习Java编程的重要参考资料,主要涵盖了Java语言的基础以及进阶知识。这本书深入浅出地讲解了Java的核心概念和技术,为读者提供了全面而细致的学习路径。以下是对该书内容的...
线程同步、锁机制(如synchronized关键字、ReentrantLock等)、并发集合(如ConcurrentHashMap)以及Executor框架都是Java进阶学习的重点。 3. **反射与动态代理**: 反射机制使得Java在运行时可以检查类的信息,...
在这一部分,你将学习到如何创建和管理线程,理解线程同步机制,包括synchronized关键字、wait/notify机制、Lock接口和ReentrantLock类,以及并发工具类如Semaphore、CountDownLatch和CyclicBarrier。 **3. 文件I/O...
- **同步机制**:学习多种线程同步工具(如`synchronized`关键字、`ReentrantLock`、`Semaphore`等)的原理与应用场合。 - **原子类与并发工具类**:介绍Java并发包中提供的原子类(如`AtomicInteger`)、`...
"Java进阶篇课后编程习题答案"提供了针对Java高级概念的练习题解答,旨在帮助学习者深入理解Java语言的核心特性,提升编程技能。下面将详细阐述Java进阶中的关键知识点,并结合课后习题可能涉及的内容进行解析。 1....
- **线程同步**:理解`synchronized`关键字、`ReentrantLock`、`Semaphore`、`CountDownLatch`、`CyclicBarrier`等同步工具的使用方法。 5. **Socket** - **Socket通信**:了解TCP/IP协议下Socket的工作原理。 -...
学习线程同步机制,如synchronized关键字、wait/notify、ReentrantLock等,以及并发工具类如Semaphore、CountDownLatch、CyclicBarrier等,用于构建高并发应用。 3. 内存管理与垃圾回收:深入理解Java内存模型,...
在Java编程领域,进阶意味着深入理解语言特性、优化代码性能、掌握高级设计模式和框架。以下是一些关键的Java...这些知识点构成了Java进阶的核心内容,通过深入学习和实践,你将能够编写出更高效、更健壮的Java应用。
### Java进阶知识 #### 1. 异常处理 - **异常类型**:了解运行时异常和编译时异常的区别。 - **异常处理机制**:掌握try-catch-finally结构;学会抛出自定义异常。 #### 2. 集合框架 - **集合接口**:理解List、...
根据提供的文件信息,我们可以推断出这是一套关于Java编程语言的核心技术书籍,分为两卷:第一卷主要介绍基础知识,第...这套书籍系统全面地介绍了Java编程语言的核心技术,适合Java初学者入门以及进阶学习者深入掌握。
### Java面试进阶讲义知识点总结 #### 一、Java语言拾遗 ##### 1、Vector与ArrayList - **起源与版本**:`Vector` 类自 JDK 1.0 就已存在,从 Java 2 平台 v1.2 开始进行了改进,实现了 `List` 接口,使其成为 ...
- **同步与锁**: 讨论同步的重要性,包括synchronized关键字、ReentrantLock等同步机制。 - **并发工具类**: 如CountDownLatch、CyclicBarrier、Semaphore等,以及它们在并发控制中的应用。 - **Executor框架**: ...