线程的安全性分析

本文深入探讨了线程安全的概念,包括可见性、原子性和有序性问题,详细解析了Happens-Before规则,并介绍了Synchronized关键字、volatile变量、原子类Atomic以及ThreadLocal的使用,旨在理解并解决多线程环境下的并发问题。
摘要由CSDN通过智能技术生成

什么是线程安全

当多个线程并发访问某个对象时,这个对象最终的属性行为符合我们预期的结果,就是线程安全的。
例如:
在这里插入图片描述
3个线程同时修改一个对象的属性,线程A需要设置这个对象属性的性别为男,如果这个时候其他线程对该对象的属性进行修改,那么线程A再次获得这个对象的属性时就是我们想要的结果,这就是线程不安全导致的。

线程安全的本质问题

  • 可见性
  • 原子性
  • 有序性

可见性问题分析

当一个线程操作共享变量时,首先从主内存中复制共享变量到自己的工作内存中,然后对工作内存中的变量进行处理,处理完成后将变量更新到主内存中。
当多个线程同时访问一个共享变量时,由于每个线程都有自己独立的工作内存缓存区,所以线程间的操作都是不可见的。
例如以下代码:

public class VisableDemo {
   

    public static boolean stop = false;

    public static void main(String[] args) throws InterruptedException {
   
        Thread thread = new Thread(()->{
   
            int i = 0;
            while(!stop){
   
                i++;
            }
            System.out.println("result:" + i);
        });

        thread.start();
        Thread.sleep(1000);
        stop = true; // 通过在主线程修改stop的值停止线程
    }
}

在主方法中是否可以通过修改stop的值来停止线程运行?
运行后发现通过这种方式不能停止线程,也就是说主线程中的stop对于子线程来说是不可见的。

原子性问题分析

原子性表示一个或者多个操作是一个不可分割的原子单元,要么都成功,要么都失败。
原子性问题是由线程切换带来的。

执行以下代码会发现,输出的count只会小于等于1000。
这是为什么呢?
首先分析线程中count++这段代码,java是一个高级语言,使用这段代码表示对count数进行累加,但是最终在JVM执行时,这段代码是分为3个步骤的。
1.拿到count的值
2.add递增
3.putStatic赋值
要满足原子性,那么这3个步骤要么成功,要么失败。

public class AtomicDemo {
   

    public static int count = 0;

    public static void incr(){
   
        try {
   
            Thread.sleep(1);
        }catch (InterruptedException e){
   
            e.printStackTrace();
        }
        count++;
    }

    public static void main(String[] args) throws InterruptedException {
   
        for (int i = 0; i < 1000; i++){
   
            new Thread(AtomicDemo::incr).start();
        }

        Thread.sleep(4000);

        System.out.println(count);
    }

}

在这里插入图片描述

有序性问题分析

在执行程序时为了提高性能,编译器和处理器常常会对指令做重排序(简单理解就是原本我们写的代码指令执行顺序应该是A→B→C,但是现在的CPU都是多核CPU,为了秀下优越,为了提高并行度,为了提高性能等,可能会出现指令顺序变为B→A→C等其他情况)。

当然CPU们也不是随便就去重排序,需要满足以下两个条件(遵循的规则):
1. 在单线程环境下不能改变程序运行的结果;
2. 存在数据依赖关系的不允许重排序。

例如:

int a = 1;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值