摘要:
1. 概述 虽然 Java 中的volatile关键字通常可以确保线程安全,但情况并非总是如此。 在本教程中,我们将了解共享volatile变量可能导致争用条件的情况。 2. 什么是volatile变量? 与其他变量不同,volatile变量是写入主存储器和从主存储器读取的。CPU 不缓存volat 阅读全文
摘要:
1. 概述 在没有必要同步的情况下,编译器、运行时或处理器可能会应用各种优化。尽管这些优化通常是有益的,但有时它们可能会导致微妙的问题。 缓存和重新排序是在并发上下文中可能会让我们感到惊讶的优化之一。Java 和 JVM 提供了许多控制内存顺序的方法,volatile关键字就是其中之一。 在本教程中 阅读全文
摘要:
1. 概述 在本教程中,我们将了解volatile关键字和原子类之间的区别以及它们解决的问题。首先,有必要知道Java如何处理线程之间的通信以及可能出现的意外问题。 线程安全是一个关键主题,它提供了对多线程应用程序内部工作的深入了解。我们还将讨论争用条件,但我们不会太深入地讨论这个主题。 2. 并发 阅读全文
摘要:
1. 概述 集合框架是Java的关键组件。它提供了大量的接口和实现,使我们能够以简单的方式创建和操作不同类型的集合。 尽管使用普通的不同步集合总体上很简单,但在多线程环境(也称为并发编程)中工作时,它也可能成为一个令人生畏且容易出错的过程。 因此,Java 平台通过在Collections类中实现的 阅读全文
摘要:
1. 概述 在本教程中,我们将学习是什么使对象不可变,如何在 Java 中实现不可变性,以及这样做有什么好处。 2. 什么是不可变对象? 不可变对象是其内部状态在完全创建后保持不变的对象。 这意味着不可变对象的公共 API 保证了它在其整个生命周期中的行为方式相同。 如果我们看一下类 String, 阅读全文
摘要:
1. 简介 在本教程中,我们将看到 Java 中一些最常见的并发问题。我们还将学习如何避免它们及其主要原因。 2. 使用线程安全对象 2.1. 共享对象 线程主要通过共享对相同对象的访问来进行通信。因此,在对象更改时从对象读取可能会产生意外的结果。此外,同时更改对象可能会使其处于损坏或不一致的状态。 阅读全文
摘要:
1. 简介 在本教程中,我们将了解什么是非阻塞数据结构,以及为什么它们是基于锁的并发数据结构的重要替代方案。 首先,我们将介绍一些术语,例如无障碍、无锁定和无等待。 其次,我们将研究非阻塞算法的基本构建块,如CAS(compare-and-swap)。 第三,我们将研究在Java中实现无锁队列,最后 阅读全文
摘要:
1. 概述 在之前的一篇文章中,我们了解到AtomicStampedReference可以防止ABA问题。 在本教程中,我们将仔细研究如何最好地使用它。 2. 为什么我们需要AtomicStampedReference? 首先,AtomicStampedReference为我们提供了一个对象引用变量 阅读全文
摘要:
1. 简介 在本教程中,我们将介绍并发编程中 ABA 问题的理论背景。我们将看到它的根本原因以及解决方案。 2. 比较和交换 为了了解根本原因,让我们简要回顾一下比较和交换的概念。 比较和交换 (CAS) 是无锁算法中的常用技术,用于确保一个线程对共享内存的更新在另一个线程同时修改相同空间时失败。 阅读全文
摘要:
1. 概述 在本文中,我们将看看JRE提供的一个引人入胜的类 - 不安全的sun.misc包。此类为我们提供了低级机制,这些机制旨在仅供核心 Java 库使用,而不能由标准用户使用。 这为我们提供了主要为核心库内部使用而设计的低级机制。 2. 获取不安全的实例 首先,为了能够使用Unsafe类,我们 阅读全文
摘要:
1. 简介 简而言之,当涉及并发时,共享可变状态很容易导致问题。如果未正确管理对共享可变对象的访问,应用程序很快就会变得容易出现一些难以检测的并发错误。 在本文中,我们将重新审视使用锁来处理并发访问,探讨与锁相关的一些缺点,最后引入原子变量作为替代方案。 2. 锁 让我们来看看: public cl 阅读全文
摘要:
1. 概述 在本教程中,我们将研究java.lang包中的ThreadLocal构造。这使我们能够单独存储当前线程的数据,并简单地将其包装在特殊类型的对象中。 2.ThreadLocal 接口 TheadLocal构造允许我们存储只能由特定线程访问的数据。 假设我们想要一个将与特定线程捆绑在一起的I 阅读全文
摘要:
1. 概述 Java 支持开箱即用的多线程。这意味着通过在单独的工作线程中并发运行字节码,JVM能够提高应用程序性能。 虽然多线程是一个强大的功能,但它是有代价的。在多线程环境中,我们需要以线程安全的方式编写实现。这意味着不同的线程可以访问相同的资源,而不会暴露错误行为或产生不可预知的结果。这种编程 阅读全文
摘要:
1. 概述 在本教程中,我们将讨论孵化器功能结构化并发 (JEP 428),它为 Java 19 提供了结构化并发功能。我们将指导你使用新的 API 来管理多线程代码。 2. 理念 通过采用并发编程风格来降低线程泄漏和取消延迟的可能性,从而增强多线程代码的可维护性、可靠性和可观察性,这是与取消和关闭 阅读全文
摘要:
1. 概述 在本文中,我们将研究java.util.concurrent包中的DelayQueue构造。这是一个阻塞队列,可用于生产者-消费者程序。 它有一个非常有用的特性——当消费者想要从队列中获取一个元素时,他们只能在该特定元素的延迟到期时获取它。 2. 为延迟队列中的元素实现延迟 我们要放入D 阅读全文
摘要:
1. 概述 软件组件的解耦是软件设计中最重要的部分之一。实现此目的的一种方法是使用消息传递系统,它提供组件(服务)之间的异步通信方式。在本文中,我们将介绍其中一个系统:RabbitMQ。 RabbitMQ 是一个实现高级消息队列协议 (AMQP) 的消息代理。它为主要编程语言提供客户端库。 除了用于 阅读全文
摘要:
1. 概述 在本教程中,我们将探索使用 Spring AMQP 框架通过 AMQP 进行基于消息的通信。首先,我们将介绍消息传递的一些关键概念。然后,我们将继续一个实际示例。 2. 基于消息的通信 消息传递是一种在应用程序之间进行通信的技术。它依赖于异步消息传递,而不是基于同步请求响应的体系结构。消 阅读全文
摘要:
1. 简介 异步消息传递是一种松散耦合的分布式通信,在实现事件驱动体系结构方面越来越流行。幸运的是,Spring框架提供了 SpringAMQP 项目,允许我们构建基于AMQP的消息传递解决方案。 另一方面,在此类环境中处理错误可能是一项艰巨的任务。因此,在本教程中,我们将介绍处理错误的不同策略。 阅读全文
摘要:
1. 简介 在多进程并发环境中,多个进程可能会争用一组有限的资源。如果进程请求资源,而该资源当前不可用,则进程将等待该资源。有时,此等待过程永远不会成功访问资源。这种对资源的等待会导致三种情况——死锁、活锁和饥饿。 在本教程中,我们将讨论这三个条件。 2. 死锁 在本节中,我们将首先讨论死锁、其必要 阅读全文
摘要:
1. 概述 虽然多线程有助于提高应用程序的性能,但它也带来了一些问题。在本教程中,我们将在 Java 示例的帮助下研究两个这样的问题,死锁和活锁。 2. 死锁 2.1. 什么是死锁? 当两个或多个线程永远等待另一个线程持有的锁或资源时,就会发生死锁。因此,应用程序可能会停止或失败,因为死锁线程无法进 阅读全文