Skip to main content

Java并发编程中的三个概念

1 原子性

一个操作或者多个操作,要么全部执行且执行的过程中不会被任何因素打断,要么都不执行。翻译一下就是:要么执行要么不执行。

银行转账问题:A给B转账10000

  1. A 账号减少 10000
  2. B 账号增加 10000

这两个操作必须是原子操作交易才能正常

Java中的简单原子操作:简单的读取、赋值(而且必须是将数字[基本数据类型]赋值给某个变量,变量之间的相互赋值不是原子操作)才是原子操作

Java保证原子性的方法:synchronized 和Lock关键字,利用同步锁保证一次只能一个线程对变量进行操作。

Java内存模型中的八种操作都是原子操作

  • lock(锁定):作用于主内存中的变量,它把一个变量标识为一个线程独占的状态
  • unlock(解锁):作用于主内存中的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定
  • read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便后面的load动作使用
  • load(载入):作用于工作内存中的变量,它把read操作从主内存中得到的变量值放入工作内存中的变量副本
  • use(使用):作用于工作内存中的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作
  • assign(赋值):作用于工作内存中的变量,它把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作
  • store(存储):作用于工作内存的变量,它把工作内存中一个变量的值传送给主内存中以便随后的write操作使用
  • write(操作):作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中

2 可见性

  • 可见性:一个线程对共享变量值的修改,能够及时地被其他线程看到
  • 共享变量:如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量(实例的成员变量在方法中使用,方法被多个线程调用).

3 有序性

即程序执行的顺序按照代码的先后顺序执行。

指令重排:一般来说,处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码顺序执行的结果是一致的

例子:

int a = 10;    //语句1
int r = 2; //语句2
a = a + 3; //语句3
r = a*a; //语句4

上面代码也可以这样执行

int r = 2;    //语句2
int a = 10; //语句1
a = a + 3; //语句3
r = a*a; //语句4

但是不能这样执行

int r = 2;    //语句2
int a = 10; //语句1
r = a*a; //语句4
a = a + 3; //语句3

这样指令重排后程序最终执行的结果和代码顺序执行的结果不相同