西维蜀黍

【Java】I/O - I/O 基本操作

I/O 简介

I/O就是输入和输出,核心是I/O流,流用于读写设备上的数据,包括硬盘文件、键盘、网络…。

  ...


【Java】字符(串)编码与解码

背景

究竟什么是字符?

众所周知,一个字符(character)就是一个字((letter),一串字母组成一个单词,一组单词组成句子,以此类推。然而,事实上,在计算机中,在屏幕上描述的字符(被称为字符的图符),和为这个字符指定的数值(被称为代码值),并不是直接对应的。

  ...


【Java】多线程 - 线程间通信工具 CountDownLatch、CyclicBarrier 和 Phaser 类

本文将介绍常用的线程间通信工具 CountDownLatch、CyclicBarrier 和Phaser 的用法,并结合实例介绍它们各自的适用场景及相同点和不同点。

  ...


【Lock】锁的几种特性

我们来介绍一下与锁相关的几个概念。

  • 可重入锁(Reentrant Lock)
  • 公平锁(fair locking)和非公平锁(unfair locking)
  • 可中断锁(Interruptable Lock)
  • 可限时锁(Timed Lock)
  • 读写锁(Read-Write Lock)
  • 自旋锁(Spin Lock)
    • 适应性自旋锁(Adaptive Spinning Lock)
  • 独享锁(Exclusive Lock) VS 共享锁(Shared Lock)
  • 偏向锁(Biased Lock)
  ...


【Java】锁 - AQS

引言

在 JDK1.5 之前,一般是靠 synchronized 关键字来实现线程对共享变量的互斥访问。synchronized是在字节码上加指令,依赖于底层操作系统的Mutex Lock实现。

而从JDK1.5以后,Java界的一位大神—— Doug Lea 开发了AbstractQueuedSynchronizer(AQS)组件,使用原生Java代码实现了synchronized语义。换句话说,Doug Lea没有使用更“高级”的机器指令,也不依靠JDK编译时的特殊处理,仅用一个普普通通的类就完成了代码块的并发访问控制,比那些费力不讨好的实现不知高到哪里去了。

java.util.concurrent包有多重要无需多言,一言以蔽之,是Doug Lea大爷对天下所有Java程序员的怜悯。

AQS定义了一套多线程访问共享资源的同步器框架,是整个java.util.concurrent包的基石,Lock、ReadWriteLock、CountDowndLatch、CyclicBarrier、Semaphore、ThreadPoolExecutor等都是在AQS的基础上实现的。

CAS(Compare And Swap)

CAS 指的是现代 CPU 广泛支持的一种对内存中的共享数据进行操作的一种特殊指令。这个指令会对内存中的共享数据做原子的读写操作。简单介绍一下这个指令的操作过程:

首先,CPU 会先获取这个要修改的值的当前值,然后进行一个原子修改操作。在这个原子操作内部,会再次当这两个值相等时,CPU 才会将内存中的数值替换为新的值。否则便不做操作。最后,CPU 会将旧的数值返回。

这一系列的操作是原子的。它们虽然看似复杂,但却是 Java 5 并发机制优于原有锁机制的根本。简单来说,CAS 的含义是“我认为原有的值应该是什么,如果是,则将原有的值更新为新值,否则不做修改,并告诉我原来的值是多少”。

CAS通过调用JNI(Java Native Interface)调用实现的。JNI允许java调用其他语言,而CAS就是借助C语言来调用CPU底层指令实现的。Unsafe是CAS的核心类,它提供了硬件级别的原子操作

Doug Lea大神在java同步器中大量使用了CAS技术,鬼斧神工的实现了多线程执行的安全性。CAS不仅在AQS的实现中随处可见,也是整个java.util.concurrent包的基石。

AQS,非阻塞数据结构和原子变量类(java.util.concurrent.atomic包中的类),这些concurrent包中的基础类都是使用这种模式来实现的,而concurrent包中的高层类又是依赖于这些基础类来实现的。从整体来看,concurrent包的实现示意图如下:

在Java中,sun.misc.Unsafe 类提供了硬件级别的原子操作来实现这个CAS。 java.util.concurrent 包下的大量类都使用了这个 Unsafe.java 类的CAS操作。

  ...