阅读 1057

JAVA并发编程-简介

并发

早期的计算机不包含系统,从头到尾只执行一个程序,操作系统的出现使得计算机每次能在不同进程中运行多个程序,并给独立的进程分配各种资源,包括内存文件句柄等,在进程之间可以通过一些粗粒度的通信机制来交换数据;但是进程间通信开销较大于是诞生了轻量级进程:线程,目前大多数操作系统都是以线程为基本的调度单位,并且同一个进程中所有线程共享进程的内存地址,所以需要能更细粒度的数据共享机制保证线程安全

安全性问题

线程的安全性非常复杂,没有正确同步的情况下,多个线程的执行顺序是不可预测的,也就是说程序的运行结果可能会超出你的预期,如下:

public class UnsafeSequence {
    private int value;
    
    /** value自增 **/
    public int getNext(){
        return value++;
    }
}
复制代码

在单线程下这个方法是完全没有问题,但是在多线程下运行1000次,最终可能并不能得到1000,我们简单分析下原因:虽然value++看上去是一个原子的操作,实际上它分为3步:

  • 读取value
  • 将value加1
  • 将计算结果赋值给value

在不同的线程下就可能造成下面的执行顺序

image.png 结果就是在不同的线程中返回了相同的值,就造成最终的结果可能小于1000,这是一种很常见也很容易忽略的并发安全问题,称为竞态条件(Race Condition)

接下来我们试着修复这个方法,让它在多线程环境下也能返回正确的结果

public class UnsafeSequence {
    private int value;
    
    /** value自增 **/
    public synchronized int getNext(){
        return value++;
    }
}
复制代码

这是最简单的修改方法,将getNext()方法定义为一个同步方法,用synchronized关键字修饰。

活跃性问题

安全性的含义是“永远不发生糟糕的事情”,而活跃性的含义是“某件正确的事最终会发生”。比如无意中造成的无限循环,死锁,饥饿,活锁都是属于活跃性问题,如何避免这些问题我们在后面的文章中讲解,这篇文章只是简单介绍下java中的并发问题,让大家有个简单的概念

文章分类
后端
文章标签