西维蜀黍

【Java】锁 - CAS 无锁算法

CAS 是怎么实现的

以 Atomic 类中的 incrementAndGet() 方法为例,其内部就调用了Unsafe中的 native 方法(CompareAndSet)以实现递增数值:

private volatile int value;
public final int get() {
        return value;
    }
/**
 * Atomically increments by one the current value.
 *
 * @return the updated value
 */
public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}
public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

我们来分析下 incrementAndGet 的逻辑:

  1. 先获取当前的value值
  2. 对value加一
  3. 第三步是关键步骤,调用compareAndSet方法来进行一个原子更新操作,这个方法的语义是:先检查当前value是否等于current,如果相等,则意味着value没被其他线程修改过,更新并返回true。如果不相等,compareAndSet则会返回false,然后循环继续尝试更新。

  ...


【Java】多线程 - Happens-before 原则

除了从应用层面保证目标代码段执行的有序性(Ordering)外,JVM 还通过被称为 happens-before 原则隐式地保证单线程执行的有序性。

  ...


【Java】多线程 - 线程安全(Thread Safety)

背景

线程安全是多线程领域的问题,线程安全可以简单理解为一个方法或者一个实例可以在多线程环境中使用而不会出现问题。

产生线程不安全的原因

在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问了相同的资源。如,同一内存区(变量,数组,或对象)、系统(数据库,web services等)或文件。实际上,这些问题只有在一或多个线程同时向这些资源进行写操作时,才可能发生。

只要资源没有发生变化,多个线程读取相同的资源仍然是安全的。

竞态条件(Race condition) & 临界区(Critical Regions)

当两个线程同时修改同一资源时,就存在竞态条件(Race condition) 。导致竞态条件发生的代码区称作临界区(Critical Regions)

通过在临界区中使用适当的同步机制(synchronization),比如互斥锁(mutex),就可以避免竞态条件。

线程安全(Thread Safety)

当一个可变(mutable)对象会被多个线程访问时,就要考虑这个线程是不是需要被设计成线程安全的。

一个类会被称为**线程安全(thread-safe)**的,当它被从多个线程访问,而且无论这些线程如何被调度(scheduling)和交叉(interleaving)执行,而且在调用代码(calling code)中不需要额外的同步(synchronization)或者其他协调(coordiantion)机制,它的行为仍然正确(若预期执行)。

换句话说,线程安全的类封装(encapsulate)了已经需要的同步机制,因此客户端或者说调用者不再需要关注或者提供这些同步机制。

  ...


【Java】多线程 - ThreadLocal

ThreadLocal 类

通常情况下,我们创建的非局部变量是可以被任何一个线程访问并修改的。而使用 ThreadLocal 创建的变量只能被当前线程访问,其他线程则无法访问和修改。

  ...


【Java】多线程 - 守护线程(Daemon Thread)

守护线程(Daemon Thread)

在 Java 中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)。

  ...


【Network】两种高性能 I/O 设计模式 - Reactor/Proactor

背景

  ...


【Java】多线程 - 线程状态切换函数

Java的线程状态

Java语言中定义了6种线程状态,在任意一个时间点,一个线程有且只有其中一种状态,这6种状态是:

  ...


【Java】多线程 - 线程池(Thread Pool)

什么是线程池(Thread Pool)?

为了避免系统频繁地创建和销毁线程,我们可以让创建的线程进行复用。

用线程时从线程池中获取,用完以后不销毁线程,而是归还给线程池(Thread Pool)。

  ...


【Operating System】进程 - 协程(Coroutines)

背景

线程模型

在现代计算机结构中,先后提出过两种线程模型:用户级线程(user-level threads)内核级线程(kernel-level threads)

  ...


【Java】JVM - Java 内存模型(Java Memory Model)

背景

重排序(Instruction Reordering)

在执行程序时为了提高性能,编译器和处理器常常会对指令做重排序。

重排序分三类:

  • 编译器优化的重排序:编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。
  • 指令级并行的重排序。现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
  • 内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
  ...