JavaEE学习总结(三)多线程--线程安全

一、什么叫线程安全

如果在多线程的环境下代码运行的结果是符合预期的,就说明这个线程是安全的。

二、线程为什么会不安全

如果多个线程对共享变量进行修改就会发生线程不安全。

  • 原子性
    没有保障原子性会导致线程不安全,由于线程的抢占式调度原则,如果一个线程在对变量操作,中途其他线程插入,结果就有可能是错误的。
  • 可见性(一个线程对共享变量的修改能及时被其他线程看到)
    由于每个线程有自己的工作内存,这些内存中的内容相当于同一个共享变量的“副本”。此时修改线程1的工作内存的值,线程2的工作内存不一定会及时变化,从而导致线程不安全。

三、如何解决线程不安全的问题

答案:加锁

  1. synchronized关键字------监视器锁
    synchronized会起到互斥效果,某个线程执行到某个对象的synchronized中时,其他线程如果也执行到这就会阻塞等待

    特性:
    进入synchronized修饰的代码块:加锁;
    退出synchronized修饰的代码块:解锁;

    刷新内存的工作机制:
    synchronized的工作过程:1.获得互斥锁-》2.从主内存拷贝最新变量副本到工作内存-》3.执行代码-》4.更改后的共享变量刷新到主内存-》5.释放互斥锁;

    可重入性:
    synchronized对同一条线程是可重入的,不会把自己锁死。

    用法:

public class SynchronizedUse {
    //1.修饰普通方法
    public synchronized void func(){
        
    }
    
    //2.修饰静态方法
    public synchronized static void func2(){
        
    }
    
    //3.修饰代码块:需明确指定对象
    public void func3(){
        synchronized (this){
            //代码。。。
        }
    }
}

2.volatile关键字
volatile修饰的变量能够保证“内存可见性”,但不保证原子性。

当代码写入volatile修饰的变量时:

  • 改变线程工作内存中volatile变量副本的值;
  • 将改变后的值刷新到主内存;

当代码读取volatile修饰的变量时:

  • 从主内存读取最新值到线程的工作内存中;
  • 从工作内存中读取volatile变量的副本。

你可能感兴趣的:(java-ee,学习,java)