随笔分类 -  Java并发编程

摘要:前言 为保证计数器中 的原子性,我们在前面使用的都是 互斥锁方案,加锁独占访问的方式未免太过霸道,于是我们来介绍另一种解决原子性问题的 无锁方案:原子变量 。在正式介绍原子变量之前,我们先来总结下锁的不足,然后深入介绍原子变量。 锁的劣势 通过对共享变量加锁,使得获取到锁的线程可以采用独占方式来访问 阅读全文
posted @ 2020-02-27 12:18 sakuraxx 阅读(724) 评论(0) 推荐(0) 编辑
摘要:前言 Java并发包有很大一部分都是关于并发容器的。Java在5.0版本之前线程安全的容器称之为 同步容器 。同步容器实现线程安全的方式:是将每个公有方法都使用 修饰,保证每次只有一个线程能访问容器的状态。但是这样的串行度太高,将严重降低并发性,当多个线程竞争容器的锁时,吞吐量将严重降低。因此,在J 阅读全文
posted @ 2020-02-23 17:22 sakuraxx 阅读(533) 评论(0) 推荐(1) 编辑
摘要:前言 下面介绍协调让多线程步调一致的两个工具类: 和`CyclicBarrier`。 CountDownLatch和CyclicBarrier的用途介绍 CountDownLatch 是一个同步工具类, 在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待 。可以指定计数初始化Cou 阅读全文
posted @ 2020-02-20 20:16 sakuraxx 阅读(515) 评论(0) 推荐(0) 编辑
摘要:前言 适用于读多写少的场景,允许多个线程同时读取共享变量。但在读多写少的场景中,还有更快的技术方案。在Java 1.8中, 提供了 锁,它的性能就比读写锁还要好。下面我们介绍StampedLock的使用方法、内部工作原理以及在使用过程中需要注意的事项。 StampedLock支持的三种锁模式 支持两 阅读全文
posted @ 2020-02-19 20:18 sakuraxx 阅读(1261) 评论(2) 推荐(1) 编辑
摘要:前言 前面介绍过 ,它实现的是一种标准的互斥锁:每次最多只有一个线程能持有ReentrantLock。这是一种强硬的加锁规则,在某些场景下会限制并发性导致不必要的抑制性能。互斥是一种保守的加锁策略,虽然可以避免“写/写”冲突和“写/读”冲突,但是同样也避免了“读/读”冲突。 在读多写少的情况下,如果 阅读全文
posted @ 2020-02-17 20:32 sakuraxx 阅读(672) 评论(0) 推荐(0) 编辑
摘要:前言 1965年,荷兰计算机科学家Dijkstra提出的信号量机制成为一种高效的进程同步机制。这之后的15年,信号量一直都是并发编程领域的终结者。1980年,管程被提出,成为继信号量之后的在并发编程领域的第二个选择。目前几乎所有的语言都支持信号量机制,Java也不例外。Java中提供了 并发工具类来 阅读全文
posted @ 2020-02-15 23:54 sakuraxx 阅读(672) 评论(0) 推荐(0) 编辑
摘要:前言 Java SDK并发包通过 和`Condition synchronized`实现了管程的,那么为什么还在SDK中提供另外一种实现呢?欲知为何请看下文。 下面将先阐述再造管程的理由,然后详细介绍Lock和Condition,最后再看实现同步机制时是选择synchronized还是SDK中的管程 阅读全文
posted @ 2020-02-09 19:12 sakuraxx 阅读(767) 评论(0) 推荐(1) 编辑
摘要:前言 下面简单总结学习Java并发的笔记,关于如何利用面向对象思想写好并发程序的建议。面向对象的思想和并发编程属于两个领域,但是在Java中这两个领域却可以融合到一起。在Java语言中,面向对象编程的思想能够让并发编程变得更加简单。下面将从封装共享变量、识别共享变量间的约束条件和制定并发访问策略三方 阅读全文
posted @ 2020-02-06 16:16 sakuraxx 阅读(365) 评论(0) 推荐(0) 编辑
摘要:前言 方法中的变量(即局部变量)是不存在数据竞争(Data Race)的,也是线程安全的。为了理解为什么,我们先来了一下方法是如何被执行的,然后再分析局部变量的安全性,最后再介绍利用局部变量不会共享的特点而产生的解决并发问题的一些技术。 方法是如何被执行的 以上代码转换成CPU指令执行,方法的调用过 阅读全文
posted @ 2020-02-05 17:05 sakuraxx 阅读(4931) 评论(0) 推荐(2) 编辑
摘要:前言 线程是操作系统中的一个概念,支持多线程的语言都是对OS中的线程进行了封装。要学好线程,就要搞清除它的生命周期,也就是生命周期各个节点的状态转换机制。不同的开发语言对操作系统中的线程进行了不同的封装,但是对于线程的声明周期这部分基本是相同的。下面先介绍通用的线程生命周期模型,然后详细介绍Java 阅读全文
posted @ 2020-01-29 23:30 sakuraxx 阅读(399) 评论(0) 推荐(0) 编辑
摘要:前言 在Java 1.5之前,Java语言提供的唯一并发语言就是管程,Java 1.5之后提供的SDK并发包也是以管程为基础的。除了Java之外,C/C++、C 等高级语言也都是支持管程的。 那么什么是管程呢? 见名知意,是指管理共享变量以及对共享变量操作的过程,让它们支持并发。翻译成Java领域的 阅读全文
posted @ 2020-01-28 20:14 sakuraxx 阅读(4973) 评论(0) 推荐(4) 编辑
摘要:前言 Java的多线程是一把双刃剑,使用好它可以使我们的程序更高效,但是出现并发问题时,我们的程序将会变得非常糟糕。并发编程中需要注意三方面的问题,分别是安全性、活跃性和性能问题。 安全性问题 我们经常说这个方法是线程安全的、这个类是线程安全的,那么到底该怎么理解线程安全呢? 要给线程安全性定一个非 阅读全文
posted @ 2020-01-27 23:51 sakuraxx 阅读(957) 评论(1) 推荐(1) 编辑
摘要:前言 在前篇介绍 "死锁" 的文章中,我们破坏等待占用且等待条件时,用了一个死循环来获取两个账本对象。 我们提到过,如果apply()操作耗时非常短,且并发冲突量也不大,这种方案还是可以。否则的话,就可能要循环上万次才可以获取锁,这样的话就太消耗CPU了! 于是我们给出另一个更好的解决方案, 等待 阅读全文
posted @ 2020-01-24 10:52 sakuraxx 阅读(1319) 评论(0) 推荐(2) 编辑
摘要:前言 我们使用加锁机制来保证线程安全,但是如果过度地使用加锁,则可能会导致死锁。下面将介绍关于死锁的相关知识以及我们在编写程序时如何预防死锁。 什么是死锁 学习操作系统时,给出死锁的定义为两个或两个以上的线程在执行过程中,由于竞争资源而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。简化一 阅读全文
posted @ 2020-01-23 00:19 sakuraxx 阅读(6493) 评论(2) 推荐(10) 编辑
摘要:前言 原子性指一个或多个操作在CPU执行的过程不被中断的特性。前面提到原子性问题产生的源头是线程切换,而线程切换依赖于CPU中断。于是得出,禁用CPU中断就可以禁止线程切换从而解决原子性问题。但是这种情况只适用于单核,多核时不适用。 以在 32 位 CPU 上执行 long 型变量的写操作为例来说明 阅读全文
posted @ 2020-01-21 00:20 sakuraxx 阅读(2321) 评论(0) 推荐(2) 编辑
摘要:前言 解决并发编程中的可见性和有序性问题最直接的方法就是禁用CPU缓存和编译器的优化。但是,禁用这两者又会影响程序性能。于是我们要做的是 按需禁用CPU缓存和编译器的优化 。 如何按需禁用CPU缓存和编译器的优化就需要提到 Java内存模型 。Java内存模型是一个复杂的规范。其中最为重要的便是 规 阅读全文
posted @ 2020-01-18 15:52 sakuraxx 阅读(755) 评论(0) 推荐(1) 编辑
摘要:前言 CPU 、内存、I/O设备之间的速度差距十分大,为了提高CPU的利用率并且平衡它们的速度差异。计算机体系结构、操作系统和编译程序都做出了改进: CPU增加了 缓存 ,用于平衡和内存之间的速度差异。 操作系统增加了 进程、线程 ,以时分复用CPU,进而均衡CPU与I/O设备之间的速度差异。 编译 阅读全文
posted @ 2020-01-16 20:19 sakuraxx 阅读(719) 评论(0) 推荐(2) 编辑
摘要:前言 可以将Java并发编程抽象为三个核心问题:分工、协作和同步。 这三个问题的产生源自对性能的需求。最初时,为提高计算机的效率,当IO在等待时不让CPU空闲,于是就出现了分时操作系统也就出现了并发。后来,多核CPU出现,不同的任务可以同时独立运行,于是就出现了并行【分工】。有了分工后,效率得到了很 阅读全文
posted @ 2020-01-13 21:10 sakuraxx 阅读(751) 评论(0) 推荐(0) 编辑