转载地址:http://blog.csdn.net/fh13760184/article/details/8551546
锁:
- 内置锁 (监视器锁): 每个java对象都可以做一个实现同步的锁,这些锁被成为内置锁. 获得锁的唯一途径就是进入有这个锁保护的代码块或方法
- 重入锁: 由于内置锁是可重入的,因此如果某个线程试图获得一个以已经由他自己持有的锁, 那么这个请求就会成功.重入意味着获取锁的操作粒度是"线程",而不是"调用"
volatile 使用条件(必须同时满足所有条件):
- 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值
- 该变量不会与其他状态变量一起纳入不变性条件中
- 在访问变量时间不需要加锁
高并发术语
术语 |
英文单词 |
描述 |
比较并交换 |
Compare and Swap |
CAS操作需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较下旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换。 |
CPU流水线 |
CPU pipeline |
CPU流水线的工作方式就象工业生产上的装配流水线,在CPU中由5~6个不同功能的电路单元组成一条指令处理流水线,然后将一条X86指令分成5~6步后再由这些电路单元分别执行,这样就能实现在一个CPU时钟周期完成一条指令,因此提高CPU的运算速度。 |
内存顺序冲突 |
Memory order violation |
内存顺序冲突一般是由假共享引起,假共享是指多个CPU同时修改同一个缓存行的不同部分而引起其中一个CPU的操作无效,当出现这个内存顺序冲突时,CPU必须清空流水线。 |
共享变量 |
在多个线程之间能够被共享的变量被称为共享变量。共享变量包括所有的实例变量,静态变量和数组元素。他们都被存放在堆内存中,Volatile只作用于共享变量。 |
|
内存屏障 |
Memory Barriers |
是一组处理器指令,用于实现对内存操作的顺序限制。 |
缓冲行 |
Cache line |
缓存中可以分配的最小存储单位。处理器填写缓存线时会加载整个缓存线,需要使用多个主内存读周期。 |
原子操作 |
Atomic operations |
不可中断的一个或一系列操作。 |
缓存行填充 |
cache line fill |
当处理器识别到从内存中读取操作数是可缓存的,处理器读取整个缓存行到适当的缓存(L1,L2,L3的或所有) |
缓存命中 |
cache hit |
如果进行高速缓存行填充操作的内存位置仍然是下次处理器访问的地址时,处理器从缓存中读取操作数,而不是从内存。 |
写命中 |
write hit |
当处理器将操作数写回到一个内存缓存的区域时,它首先会检查这个缓存的内存地址是否在缓存行中,如果存在一个有效的缓存行,则处理器将这个操作数写回到缓存,而不是写回到内存,这个操作被称为写命中。 |
synchronized
volatile
concurrent
在并发编程中很常用的实用工具类。此包包括了几个小的、已标准化的可扩展框架,以及一些提供有用功能的类,没有这些类,这些功能会很难实现或实现起来冗长乏味。下面简要描述主要的组件。另请参阅 locks 和 atomic 包。
执行程序
接口。Executor
是一个简单的标准化接口,用于定义类似于线程的自定义子系统,包括线程池、异步 IO 和轻量级任务框架。根据所使用的具体 Executor 类的不同,可能在新创建的线程中,现有的任务执行线程中,或者调用 execute() 的线程中执行任务,并且可能顺序或并发执行。ExecutorService
提供了多个完整的异步任务执行框架。ExecutorService 管理任务的排队和安排,并允许受控制的关闭。ScheduledExecutorService
子接口及相关的接口添加了对延迟的和定期任务执行的支持。ExecutorService 提供了安排异步执行的方法,可执行由 Callable
表示的任何函数,结果类似于 Runnable
。Future
返回函数的结果,允许确定执行是否完成,并提供取消执行的方法。RunnableFuture
是拥有 run 方法的 Future,run 方法执行时将设置其结果。
实现。类 ThreadPoolExecutor
和 ScheduledThreadPoolExecutor
提供可调的、灵活的线程池。Executors
类提供大多数 Executor 的常见类型和配置的工厂方法,以及使用它们的几种实用工具方法。其他基于 Executor 的实用工具包括具体类 FutureTask
,它提供 Future 的常见可扩展实现,以及 ExecutorCompletionService
,它有助于协调对异步任务组的处理。
队列
java.util.concurrent ConcurrentLinkedQueue
类提供了高效的、可伸缩的、线程安全的非阻塞 FIFO 队列。java.util.concurrent 中的五个实现都支持扩展的 BlockingQueue
接口,该接口定义了 put 和 take 的阻塞版本:LinkedBlockingQueue
、ArrayBlockingQueue
、SynchronousQueue
、PriorityBlockingQueue
和 DelayQueue
。这些不同的类覆盖了生产者-使用者、消息传递、并行任务执行和相关并发设计的大多数常见使用的上下文。BlockingDeque
接口扩展 BlockingQueue,以支持 FIFO 和 LIFO(基于堆栈)操作。LinkedBlockingDeque
类提供一个实现。
计时
TimeUnit
类为指定和控制基于超时的操作提供了多重粒度(包括纳秒级)。该包中的大多数类除了包含不确定的等待之外,还包含基于超时的操作。在使用超时的所有情况中,超时指定了在表明已超时前该方法应该等待的最少时间。在超时发生后,实现会“尽力”检测超时。但是,在检测超时与超时之后再次实际执行线程之间可能要经过不确定的时间。接受超时期参数的所有方法将小于等于 0 的值视为根本不会等待。要“永远”等待,可以使用 Long.MAX_VALUE 值。
同步器
四个类可协助实现常见的专用同步语句。Semaphore
是一个经典的并发工具。CountDownLatch
是一个极其简单但又极其常用的实用工具,用于在保持给定数目的信号、事件或条件前阻塞执行。CyclicBarrier
是一个可重置的多路同步点,在某些并行编程风格中很有用。Exchanger
允许两个线程在 collection 点交换对象,它在多流水线设计中是有用的。
并发 Collection
除队列外,此包还提供了设计用于多线程上下文中的 Collection 实现:ConcurrentHashMap
、ConcurrentSkipListMap
、ConcurrentSkipListSet
、CopyOnWriteArrayList
和 CopyOnWriteArraySet
。当期望许多线程访问一个给定 collection 时,ConcurrentHashMap 通常优于同步的 HashMap,ConcurrentSkipListMap 通常优于同步的 TreeMap。当期望的读数和遍历远远大于列表的更新数时,CopyOnWriteArrayList 优于同步的 ArrayList。
此包中与某些类一起使用的“Concurrent&rdquo前缀;是一种简写,表明与类似的“同步”类有所不同。例如,java.util.Hashtable 和Collections.synchronizedMap(new HashMap()) 是同步的,但 ConcurrentHashMap
则是“并发的”。并发 collection 是线程安全的,但是不受单个排他锁的管理。在 ConcurrentHashMap 这一特定情况下,它可以安全地允许进行任意数目的并发读取,以及数目可调的并发写入。需要通过单个锁不允许对 collection 的所有访问时,“同步”类是很有用的,其代价是较差的可伸缩性。在期望多个线程访问公共 collection 的其他情况中,通常“并发”版本要更好一些。当 collection 是未共享的,或者仅保持其他锁时 collection 是可访问的情况下,非同步 collection 则要更好一些。
大多数并发 Collection 实现(包括大多数 Queue)与常规的 java.util 约定也不同,因为它们的迭代器提供了弱一致的,而不是快速失败的遍历。弱一致的迭代器是线程安全的,但是在迭代时没有必要冻结 collection,所以它不一定反映自迭代器创建以来的所有更新。
内存一致性属性
Java Language Specification 第 17 章定义了内存操作(如共享变量的读写)的 happen-before 关系。只有写入操作 happen-before 读取操作时,才保证一个线程写入的结果对另一个线程的读取是可视的。synchronized
和 volatile
构造 happen-before 关系,Thread.start()
和Thread.join()
方法形成 happen-before 关系。尤其是:
- 线程中的每个操作 happen-before 稍后按程序顺序传入的该线程中的每个操作。
- 一个解除锁监视器的(
synchronized
阻塞或方法退出)happen-before 相同监视器的每个后续锁(synchronized
阻塞或方法进入)。并且因为 happen-before 关系是可传递的,所以解除锁定之前的线程的所有操作 happen-before 锁定该监视器的任何线程后续的所有操作。 - 写入
volatile
字段 happen-before 每个后续读取相同字段。volatile
字段的读取和写入与进入和退出监视器具有相似的内存一致性效果,但不 需要互斥锁。 - 在线程上调用
start
happen-before 已启动的线程中的任何线程。 - 线程中的所有操作 happen-before 从该线程上的
join
成功返回的任何其他线程。
java.util.concurrent
中所有类的方法及其子包扩展了这些对更高级别同步的保证。尤其是:
- 线程中将一个对象放入任何并发 collection 之前的操作 happen-before 从另一线程中的 collection 访问或移除该元素的后续操作。
- 线程中向
Executor
提交Runnable
之前的操作 happen-before 其执行开始。同样适用于向ExecutorService
提交Callables
。 - 异步计算(由
Future
表示)所采取的操作 happen-before 通过另一线程中Future.get()
获取结果后续的操作。 - “释放”同步储存方法(如
Lock.unlock
、Semaphore.release
和CountDownLatch.countDown
)之前的操作 happen-before 另一线程中相同同步储存对象成功“获取”方法(如Lock.lock
、Semaphore.acquire
、Condition.await
和CountDownLatch.await
)的后续操作。 - 对于通过
Exchanger
成功交换对象的每个线程对,每个线程中exchange()
之前的操作 happen-before 另一线程中对应exchange()
后续的操作。 - 调用
CyclicBarrier.await
之前的操作 happen-before 屏障操作所执行的操作,屏障操作所执行的操作 happen-before 从另一线程中对应await
成功返回的后续操作。
Condition
Condition
将 Object
监视器方法(wait
、notify
和 notifyAll
)分解成截然不同的对象,以便通过将这些对象与任意 Lock
实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock
替代了 synchronized
方法和语句的使用,Condition
替代了 Object 监视器方法的使用。
条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait
做的那样。
Condition
实例实质上被绑定到一个锁上。要为特定 Lock
实例获得 Condition
实例,请使用其 newCondition()
方法。
作为一个示例,假定有一个绑定的缓冲区,它支持 put
和 take
方法。如果试图在空的缓冲区上执行 take
操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行 put
操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存 put
线程和 take
线程,这样就可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程。可以使用两个 Condition
实例来做到这一点。
class BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100]; int putptr, takeptr, count; public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) notFull.await(); items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; notEmpty.signal(); } finally { lock.unlock(); } } public Object take() throws InterruptedException { lock.lock(); try { while (count == 0) notEmpty.await(); Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0; --count; notFull.signal(); return x; } finally { lock.unlock(); } } }
(ArrayBlockingQueue
类提供了这项功能,因此没有理由去实现这个示例类。)
Condition
实现可以提供不同于 Object
监视器方法的行为和语义,比如受保证的通知排序,或者在执行通知时不需要保持一个锁。如果某个实现提供了这样特殊的语义,则该实现必须记录这些语义。
注意,Condition
实例只是一些普通的对象,它们自身可以用作 synchronized
语句中的目标,并且可以调用自己的 wait
和notification
监视器方法。获取 Condition
实例的监视器锁或者使用其监视器方法,与获取和该 Condition
相关的 Lock
或使用其 waiting
和 signalling
方法没有什么特定的关系。为了避免混淆,建议除了在其自身的实现中之外,切勿以这种方式使用Condition
实例。
除非另行说明,否则为任何参数传递 null
值将导致抛出 NullPointerException
。
实现注意事项
在等待 Condition
时,允许发生“虚假唤醒”,这通常作为对基础平台语义的让步。对于大多数应用程序,这带来的实际影响很小,因为 Condition
应该总是在一个循环中被等待,并测试正被等待的状态声明。某个实现可以随意移除可能的虚假唤醒,但建议应用程序程序员总是假定这些虚假唤醒可能发生,因此总是在一个循环中等待。
三种形式的条件等待(可中断、不可中断和超时)在一些平台上的实现以及它们的性能特征可能会有所不同。尤其是它可能很难提供这些特性和维护特定语义,比如排序保证。更进一步地说,中断线程实际挂起的能力在所有平台上并不是总是可行的。
因此,并不要求某个实现为所有三种形式的等待定义完全相同的保证或语义,也不要求其支持中断线程的实际挂起。
要求实现清楚地记录每个等待方法提供的语义和保证,在某个实现不支持中断线程的挂起时,它必须遵从此接口中定义的中断语义。
相关推荐
《实战Java高并发程序设计》这本书正是一本专注于这一主题的资源,它旨在帮助读者深入理解如何在Java环境中构建可扩展、高效且稳定的高并发应用。 首先,我们要理解什么是高并发。高并发是指在短时间内系统能够同时...
《Java高并发程序设计》是一本深入探讨Java平台上的并发编程技术的专业书籍,由葛一鸣等人编著。这本书旨在帮助读者理解并掌握在高并发环境下编写高效、稳定且可扩展的Java应用程序的关键技巧和最佳实践。以下是该书...
Java高并发编程是Java开发中的重要领域,尤其在大规模分布式系统和互联网应用中,对高并发处理能力的要求日益提升。本资源包含了一套完整的Java高并发视频教学,以及相关的实战项目和面试题目,旨在帮助开发者深入...
《实战Java高并发程序设计》是一本专注于Java并发编程实践的书籍,试读版提供了前两章的内容,为读者提供了一个初步了解并发编程基础的窗口。在Java领域,并发编程是构建高性能、高效率系统的关键技术,对于软件开发...
《实战Java高并发程序设计》第二版是一本深入探讨Java多线程和并发编程的书籍。这本书涵盖了Java并发编程的核心概念和技术,旨在帮助开发者在实际项目中高效地处理高并发场景。随书附带的代码提供了丰富的示例,以便...
以上只是Java高并发解决思路的一部分,实际应用中还需要结合具体业务场景和性能需求进行选择和优化。"高并发web架构.pdf"文档中的实例将进一步细化这些概念,提供实践指导。在学习过程中,理论与实践相结合,才能更...
##### 3.2 Java高并发的关键技术 - **缓存机制**:使用如Redis等缓存技术减少数据库访问压力。 - **负载均衡**:利用负载均衡器(如Nginx)分散请求到不同的服务器节点。 - **异步处理**:通过消息队列(如RabbitMQ...
通过理解以上知识点,并结合"实战Java高并发程序设计模式"的学习,开发者能够更好地应对复杂并发环境下的挑战,设计出稳定、高效的Java应用程序。在学习过程中,不断实践和优化代码,是提升并发编程能力的关键。
根据提供的信息,我们可以深入探讨...通过以上介绍可以看出,Java高并发编程涉及到许多关键技术和细节,需要开发者具备扎实的基础知识和实践经验。希望本文能帮助读者更好地理解和掌握Java高并发编程的核心概念和技术。
以上内容仅是Java高并发程序设计模式的一部分知识点,实际应用中还需要结合具体业务场景和性能需求,选择合适的设计模式和并发策略,进行优化和调整。通过深入学习和实践,可以有效提升Java高并发系统的性能和稳定性...
在本文中,我们将深入探讨Java高并发系统设计的相关知识点,包括基础概念、核心技术以及最佳实践。 1. **并发编程基础** - **线程与进程**:线程是操作系统调度的基本单位,而进程则是拥有独立资源的执行单元。 -...
《Java高并发编程》第一版是一本专注于Java平台上的并发编程技术的专业书籍。在Java开发领域,高并发编程是至关重要的技能,特别是在大型分布式系统、云计算以及互联网应用中。本书旨在帮助开发者理解和掌握如何在...
综上所述,Java高并发秒杀API涉及的技术点广泛,需要开发者具备扎实的Java基础,熟悉数据库原理,了解并发控制和性能优化策略,并且掌握一定的分布式系统知识。通过不断学习和实践,我们可以构建出高效、稳定的秒杀...
《实战JAVA高并发程序设计源代码汇总版》是针对JAVA并发编程领域的一份宝贵资源,它集合了《实战JAVA高并发程序设计》一书中的核心示例代码,旨在帮助开发者深入理解和实践JAVA并发编程的关键技术。这个压缩包包含了...
通过学习《实战Java高并发程序设计》,开发者不仅可以掌握Java并发编程的基础知识,还能了解如何在实际项目中有效地应用这些知识,提升软件的性能和可扩展性。这本书是Java开发者的必备参考资料,对于提升并发编程...
《葛一鸣实战Java高并发程序设计》源码解析 在Java编程领域,高并发程序设计是一项关键且复杂的技能,涉及到多线程、同步机制、并发控制、性能优化等多个方面。该资源“葛一鸣实战Java高并发程序设计”提供了一套...
本资源是【Java 知识图谱】(高清、超详细),包含Java的全部基础知识点、Java高端开发知识点,Java常用开发框架(Spring、Springboot、SpringMVC、Mybatis等)以及Java web开发及相关数据库的知识点汇总,高并发、...
通过深入研究"实战java高并发程序设计"的源码,开发者可以学习如何在实际项目中应用以上知识点,提高程序性能和稳定性。在实践中,理解并发原理、熟练掌握同步机制、合理使用线程池以及避免并发陷阱,都是Java并发...
《实战Java高并发程序设计》是一...通过学习《实战Java高并发程序设计》,开发者能够掌握上述知识点,并能够根据实际项目需求,设计出高效、安全的并发程序。这本书对于提升Java并发编程的实践能力和理论知识大有裨益。
《实战Java高并发程序设计》是一本专注于Java并发编程实践的书籍,随书代码提供了大量示例,帮助读者深入理解并掌握在实际开发中如何处理高并发场景下的问题。本书的核心知识点涵盖了Java并发编程的基础理论、核心...