详细剖析多线程2----线程安全问题(面试高频考点)(1),2024年最新2024年网络安全程序员职业规划

本文详细探讨了多线程中的线程安全问题,包括操作系统线程的抢占式执行导致的不安全性、共享资源引发的竞态条件和数据不一致,以及非原子操作带来的风险。文章介绍了通过synchronized关键字实现的互斥和可重入特性解决线程安全问题,同时讨论了死锁的产生和避免策略,如指定加锁顺序以破坏循环等待条件。最后提到了内存可见性问题对线程安全的影响。
摘要由CSDN通过智能技术生成

由此总结线程不安全的原因-----

  1. 【根本原因】==操作系统上的线程是“抢占式执行”的,线程调度是随机的,==这是线程不安全的一个主要原因。随机调度会导致在多线程环境下,程序的执行顺序不确定,程序员必须确保无论哪种执行顺序,代码都能正常运行。
  2. 【代码结构】共享资源:多个线程同时访问并修改共享的数据或资源。当多个线程同时访问和修改共享资源时容易引发竞态条件和数据不一致的问题。
    ①一个线程修改一个变量是安全的
    ②多个线程修改一个变量是不安全的
    ③多个线程修改不同变量是安全的
  3. 【直接原因】多线程操作不是“原子的”。多线程操作中的原子性指的是一个操作是不可中断的,要么全部执行完成,要么都不执行,不能被其他线程干扰。这对于并发编程非常重要,因为如果一个操作在执行过程中被中断,可能导致数据不一致或者其他意外情况发生。(在上述多线程操作中,count++操作不是“原子的”,而是由多个CPU指令组成的,一个线程执行这些指令时,可能会在执行过程中被抢占,从而给其他线程“可乘之机”。要保证原子性操作,每个CPU指令都应该是“原子的”,即要么完全执行,要么完全不执行。)
  4. 内存可见性问题:在多线程环境下调用不可重入的函数(即不支持多线程调用的函数),可能导致数据混乱或程序崩溃。
  5. 指令重排序问题:在多线程环境下,由于编译器或处理器对指令进行重排序优化,可能导致预期之外的程序行为。

三、解决线程不安全问题–加锁(synchronized)

针对前述代码我们通过加锁解决线程安全问题

private static int count=0;
    public static void main(String[] args) throws InterruptedException {
        Object locker=new Object();
        Thread t1=new Thread(()->{
            for (int i = 0; i < 50000; i++) {
                synchronized (locker){
                    count++;
                }
            }
        });
        Thread t2=new Thread(()->{
            for (int i = 0; i < 50000; i++) {
                synchronized (locker){
                    count++;
                }
            }
        });
        t1.start();
        t2.start();
        // 如果没有这俩 join, 肯定不⾏的. 线程还没⾃增完, 就开始打印了. 很可能打印出来的 cou
        t1.join();
        t2.join();
        // 预期结果应该是 10w
        System.out.println("count: " + count);
    }

synchronized的特性

1)互斥
synchronized 会起到互

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值