Java并发编程实战-基础知识-线程安全性

要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享和可变的状态的访问。

“共享”意味着变量可以有多个线程同事访问,而“可变”则意味着变量的值在其生命周期内可以发送变化。

Java中的主要同步机制是关键字synchronized,它提供了一种独占的加锁方式,但“同步”这个术语还包括volatile类型的变量,显示锁(Explicit Lock)以及原子变量

什么是线程安全性

当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替进行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。

正确性:某个类的行为与其规范相一致。

原子性

竞态条件(Race Condition):当某个计算的正确性取决于多个线程的交替执行的时序时,那么就会发生竞态条件。

最常见的竞态条件类型就是“先检查后执行(Check-Then-Act)”操作,即通过一个可能失效的观测结果来决定下一步的动作。

public class LazyInitRace{
    private ExpensiveObject instance = null;
    
    public ExpensiveObject getInstance() {
        if(instance == null) {
            instance = new ExpensiveObject();
        }
        return instance;
    }
}

如果线程A调用getInstance时,检测instance为null,则取创建一个实例,假设在还未创建成功前,线程B也调用了getInstance,检测到instance也为null,这时两个线程都会去创建新实例,那么这两次调用可能会得到不同的结果。

引用书中定义:假定有两个操作A和B,如果从执行A的线程来看,当另一个线程执行B时,要么将B完全执行完,要么完全不执行B,那么A和B对彼此来说是原子的。原子操作是指:对于访问同一个状态的所有操作(包括该操作本身)来说,这个操作是一个以原子方式执行的操作。

我理解的是,对一个变量的操作集,要么不执行,要么全部执行完,那么这个操作集就是原子方式执行的。

内置锁

重入

如果某个线程视图获得一个已经由它自己持有的锁,那么这个请求就会成功。

重入意味着获取锁的操作的粒度是“线程”,而不是“调用”。重入的一种实现方式是,为每个锁关联一个获取计数值和一个所有者线程。

你可能感兴趣的:(java)