JAVA_线程安全问题

文章讨论了在多线程环境下,由于并发执行导致的线程安全问题。通过一个简单的`count++`操作示例,说明了两个线程并发修改共享变量时可能出现的结果不一致,即线程不安全。这与事务的脏读问题类似,其中一个线程读取到了另一个未完成操作的数据。文章末尾提出,解决线程安全问题的方法将在后续分析中探讨。
摘要由CSDN通过智能技术生成

什么情况下会发生线程安全问题?什么样的代码会设计线程安全问题?

 


多线程实现方法:继承(extends)Thread类 ;实现(implements)Runnable接口;   

根本原因:多线程的抢占式执行和随机性

假设如果程序代码都是固定单线程取执行,代码的顺序固定,程序的结果就是固定的。因为单线程就只有一条路可以走。

一个进程有多个线程组成,而在多线程的情况下,程序要抢占cpu的核心去执行代码,代码的执行顺序就会有变化。因为不同时间、不同的cpu内执行代码,就会产生无数种不同的情况,就需要保证者无数种线程去按照一定的顺序进行运行,来保证结果的正确性。只要这些结果有一种时不正确的,就会产生bug,也就是线程不安全。

例子:

   class Counter{
    public int count;
    public void add(){
        count++;
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        Counter counter = new Counter();
        Thread t1 = new Thread(()->{
        //t1线程让count加5000次
            for (int i = 0; i < 5000; i++) {
                counter.add();
            }
        });
        //t2线程让count加5000次
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                counter.add();
            }
        });
        t1.start();
        t2.start();
        //main主线程等待t1,和t2的结束
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("count的值是" + counter.count);
    }
}

 

 显然答案并不是1_0000,而且两次的答案都不是一样的,程序并不符合需求,出现了bug,这也就是典型的线程安全问题。

分析:

count++这个操作,包括三个步骤:

1、首先把内存中的值,读取到CPU的寄存器中(load)

2、把CPU寄存器里的数值进行+1运算

3、把得到的结果存在内存中

如果是两个线程并发去执行这count++这个操作,就相当于两组load、add、save进行此时不同的线程调度顺序,就可能产生一些结果上的差异

画出时间、t1、t2和内存和寄存器分析:🧐

 

 其实这个和事务的脏读问题是相似的,读到未提交(read uncommitted)是一样的。相当于t2读到的是一个t1还没提交的脏数据

怎么解决?请听下回分析

 

             

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值