线程安全和多线程三要素

 一、线程安全

1.什么是线程安全

    线程安全就是当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的。
    - 通俗来讲,如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的,或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题 。
 

2. 线程安全级别

- 线程安全也是有几个级别
    - 不可变:
        - 像String、Integer、Long这些,都是final类型的类,任何一个线程都改变不了它们的值,要改变除非新创建一个,因此这些不可变对象不需要任何同步手段就可以直接在多线程环境下使用
    - 绝对线程安全
        - 不管运行时环境如何,调用者都不需要额外的同步措施。要做到这一点通常需要付出许多额外的代价,Java中标注自己是线程安全的类,实际上绝大多数都不是线程安全的,不过绝对线程安全的类,Java中也有,比方说CopyOnWriteArrayList、CopyOnWriteArraySet
    - 相对线程安全
        - 相对线程安全也就是我们通常意义上所说的线程安全,像Vector这种,add、remove方法都是原子操作,不会被打断,但也仅限于此,如果有个线程在遍历某个Vector、有个线程同时在add这个Vector,99%的情况下都会出现ConcurrentModificationException,也就是fail-fast机制。
    - 线程非安全
        - ArrayList、LinkedList、HashMap等都是线程非安全的类.


3.线程安全需要保证几个基本特性


    - 1、原子性,简单说就是相关操作不会中途被其他线程干扰,一般通过同步机制实现。
    - 2、可见性,是一个线程修改了某个共享变量,其状态能够立即被其他线程知晓,通常被解释为将线程本地状态反映到主内存上,volatile 就是负责保证可见性的。
    - 3、有序性,是保证线程内串行语义,避免指令重排等。


二、多线程三要素

1 .三要素分别是啥

- 三要素分别是:原子性,可见性,有序性

 2. 如何理解原子性

  即一个操作(有可能包含有多个子操作)要么全部执行(生效),要么全部都不执行(都不生效)。
 

3.如何理解可见性

 - 当多个线程并发访问共享变量时,一个线程对共享变量的修改,其它线程能够立即看到。


 4. 如何理解有序性

 - 顺序性指的是,程序执行的顺序按照代码的先后顺序执行。
 

三、如何实现线程安全

保证线程安全可从多线程三特性出发:
    - 原子性(Atomicity):单个或多个操作是要么全部执行,要么都不执行
        - Lock:保证同时只有一个线程能拿到锁,并执行申请锁和释放锁的代码
        - synchronized:对线程加独占锁,被它修饰的类/方法/变量只允许一个线程访问
    - 可见性(Visibility):当一个线程修改了共享变量的值,其他线程能够立即得知这个修改
        - volatile:保证新值能立即同步到主内存,且每次使用前立即从主内存刷新;
        - synchronized:在释放锁之前会将工作内存新值更新到主存中
    - 有序性(Ordering):程序代码按照指令顺序执行
        - volatile: 本身就包含了禁止指令重排序的语义
        - synchronized:保证一个变量在同一个时刻只允许一条线程对其进行lock操作,使得持有同一个锁的两个同步块只能串行地进入

你可能感兴趣的:(多线程,线程安全,多线程三要素,如何实现线程安全)