java并发编程学习笔记(一)初识并发原子性

时间:2023-12-18 09:15:26

1、并发的意义

现在是一个多核的时代,并发的存在意义就是为了能够充分利用多核计算机的优势,提高程序的运行效率;

2、并发的风险

竞争-----多个线程对内存数据数据进行读写操作时,对数据处理结果的一个竞争。(笔者是这么认为的)

使用以下的例子来说明并发的风险:由于该方法中的value++操作不是原子性的,是分为读->运算->赋值 这3个步骤的。

假如线程A执行了读,正准备开始运算的时候,线程B开始调用这个实例的getNext方法,那么这个时候线程B读取的数据与线程A读取的数据是一样的。

即A获得的结果是value=value+1;线程B运算也是value=value+1;然而线程B在线程A之后才调用这个方法,按照假设,线程B应该返回value+2才对。

ps:文字描述的value就是初始值。

public class  demo {

 private int value;

  public int getNext(){
return value++;
}
}

 3、上述问题产生的原因有2个:

1 线程共享内存的地址空间(即内存数据对2个线程都可见)

2 getNext方法并不是原子性的(内部代码执行是可分割的)

这样就容易产生 竞争条件。

总结:线程共享相同的内存地址空间,可以访问或修改其他线程正在使用的变量。这对于线程间的通信,是十分方便的。但是其中存在着数据意外变更的风险,因此访问共享的内存变量时,线程需要经过合理的调度,才能保证程序的正常运行。

4、要纠正上述问题,可以从2个方面着手,现在先从第二个原因来着手解决。(非原子化操作)

目标1:将value++的操作原子化。

使用原子类AutomicInterger  来代替 int类型

自增操作就可以写为value.incrementAndGet();

这样一来,线程对数据的操作就是原子化的,不会出现竞争条件。

目标2:内存数据对2个线程同时都可读写,可使用->修改为以下状态

状态一:只对单个线程可读写(某个线程正在使用该对象时,另一个线程无法获取并使用该对象,另一个线程进入阻塞状态)

状态二:两个线程都可读,但是只对一个线程开放数据修改权限

以上两个状态:需要使用到锁,在下一节中做详细介绍。