Java多线程并发编程 并发三大要素

所属分类: 软件编程 / java 阅读数: 49
收藏 0 赞 0 分享

一、原子性

原子,一个不可再被分割的颗粒。原子性,指的是一个或多个不能再被分割的操作。

int i = 1; // 原子操作
i++; // 非原子操作,从主内存读取 i 到线程工作内存,进行 +1,再把 i 写到朱内存。

虽然读取和写入都是原子操作,但合起来就不属于原子操作,我们又叫这种为“复合操作”。

我们可以用synchronized 或 Lock 来把这个复合操作“变成”原子操作。

例子:

 private synchronized void increase(){
    i++;
  }

 private int i = 0;
  Lock mLock = new ReentrantLock();

  private void increase() {
    mLock.lock();
    try {
      i++;
    } finally{
      mLock.unlock();
    }
  }

这样我们就可以把这个一个方法看做一个整体,一个不可分割的整体。

除此之前,我们还可以用java.util.concurrent.atomic里的原子变量类,可以确保所有对计数器状态访问的操作都是原子的。

例子:

AtomicInteger mAtomicInteger = new AtomicInteger(0);
 
  private void increase(){
    mAtomicInteger.incrementAndGet();
  }

二、可见性

当多线程访问某一个(同一个)变量时,其中一条线程对此变量作出修改,其他线程可以立刻读取到最新修改后的变量。

int i = 0;
// 线程 1 执行
i++;

// 线程 2 执行
System.out.print("i=" + i);

即使是在执行完线程里的 i++ 后再执行线程 2,线程 2 的输入结果也会有 2 个种情况,一个是 0 和 1。

因为 i++ 在线程 1(CPU1)中做完了运算,并没有立刻更新到主内存当中,而线程 2(CPU2)就去主内存当中读取并打印,此时打印的就是 0。

synchronized和Lock能够保证可见性。

另外volatile关键字也可以解决这个问题(下一篇会讲到)。

三、有序性

我们都知道处理器为了拥有更好的运算效率,会自动优化、排序执行我们写的代码,但会确保执行结果不变。

例子:

int a = 0; // 语句 1
int b = 0; // 语句 2
i++; // 语句 3
b++; // 语句 4

这一段代码的执行顺序很有可能不是按上面的 1、2、3、4 来依次执行,因为 1 和 2 没有数据依赖,3 和 4 没有数据依赖, 2、1、4、3 这样来执行可以吗?完全没问题,处理器会自动帮我们排序。

在单线程看来并没有什么问题,但在多线程则很容易出现问题。

再来个例子:

// 线程 1
init();
inited = true;

// 线程 2
while(inited){
	work();
}

init(); 与 inited = true; 并没有数据的依赖,在单线程看来,如果把两句的代码调换好像也不会出现问题。

但此时处于一个多线程的环境,而处理器真的把这两句代码重新排序,那问题就出现了,若线程 1 先执行 inited = true; 此时,init() 并没有执行,线程 2 就已经开始调用 work() 方法,此时很可能造成一些奔溃或其他 BUG 的出现。

synchronized和Lock能确保原子性,能让多线程执行代码的时候依次按顺序执行,自然就具有有序性。

而volatile关键字也可以解决这个问题,volatile 关键字可以保证有序性,让处理器不会把这行代码进行优化排序。

更多精彩内容其他人还在看

spring boot 静态资源处理方法

本篇文章主要介绍了spring boot 静态资源处理方法。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

详解spring boot 使用application.properties 进行外部配置

这篇文章主要介绍了详解spring boot 使用application.properties 进行外部配置,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Java实现分页的前台页面和后台代码

这篇文章主要为大家详细介绍了Java实现分页的前台页面和后台代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

详解spring面向切面aop拦截器

spring中有很多概念和名词,比如过滤器、拦截器、aop等。这篇文章主要介绍了详解spring面向切面aop拦截器,有兴趣的可以了解一下。
收藏 0 赞 0 分享

Java easyui树形表格TreeGrid的实现代码

这篇文章主要为大家详细介绍了Java easyui树形表格TreeGrid的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Java的NIO与IO的详解及对比

这篇文章主要介绍了Java的NIO与IO的详解及对比的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Java中网络IO的实现方式(BIO、NIO、AIO)介绍

这篇文章主要介绍了Java中网络IO的实现方式(BIO、NIO、AIO)介绍的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Java 敏感信息加密处理

本文主要介绍了Java 敏感信息加密处理的相关知识:1)敏感信息加密处理我们要实现什么;2)敏感信息加密处理我做了些什么;3)敏感信息加密实现方法。具有很好的参考价值,下面跟着小编一起来看下吧
收藏 0 赞 0 分享

详解使用Spring3 实现用户登录以及权限认证

这篇文章主要介绍了详解使用Spring3 实现用户登录以及权限认证,这里整理了详细的代码,有需要的小伙伴可以参考下。
收藏 0 赞 0 分享

Java的内存机制详解

本文主要介绍了Java的内存机制的相关知识,具有很好的参考价值,下面跟着小编一起来看下吧
收藏 0 赞 0 分享
查看更多