线程安全问题

简介: 线程安全问题

1.什么是线程安全问题 ?


    多个线程,同时操作同一个共享资源的时候,可能会出现业务安全问题

 

场景: 小明和小红是一对夫妻,他们有一个共同的账户,余额是10万元,

如果小明和小红同时来取钱,并且2人各自都在取钱10万元,可能会出现什么问题呢?


解决方法一:同步代码块


 作用: 把访问共享资源的核心代码给上锁,以此保证线程安全


synchronized(同心锁){

   访问共享资源的核心代码

}


原理: 每次只允许一个线程加锁后进入,执行完毕后自动解锁,其他线程才可以进来执行


同步锁的注意事项:对于当前同时执行的线程来说,同步锁必须是同一把(同一个对象),否则会出bug


锁对象的使用规范:

建议使用共享资源作为锁对象,对于实例方法建议使用this作为锁对象

对于静态方法建议使用字节码(类名.class)对象作为锁对象

 public void drawMoney(double money) {
        // 同步代码块
 
        // 先搞清楚是谁来取钱
        String name=Thread.currentThread().getName();
        synchronized (this){
        // 判断余额是否足够?
        if (this.getMoney()>=money){
            System.out.println(name+"取钱成功"+money);
            // 更新余额
            this.money-=money;
            System.out.println(name+"来取钱成功后剩余"+this.money);
        }
        else {
            System.out.println("余额不够哦");
        }
    }
    }

解决方法二:同步方法



作用:把访问共享资源的核心方法给上锁,以此保证线程安全


修饰符 synchronized 返回值类型 方法名称 (){

           操作共享资源的代码

}


原理:每次只能进入一个线程进去,进去后会上锁,出来后会自动解锁,同步方法其实底层也是有隐式锁对象的,只是锁的范围是整个方法代码


如果方法是实例方法:同步方法默认用this作为的锁对象

如果方法是静态方法:同步方法默认用类名.class作为的锁对象


    是同步代码块好还是同步方法好一点?

范围上 : 同步代码块锁的范围更小,同步方法锁的范围更大

可读性: 同步方法更好

 // 同步方法
    public synchronized void drawMoney(double money) {
 
        // 先搞清楚是谁来取钱
        String name=Thread.currentThread().getName();
 
        // 判断余额是否足够?
        if (this.getMoney()>=money){
            System.out.println(name+"取钱成功"+money);
            // 更新余额
            this.money-=money;
            System.out.println(name+"来取钱成功后剩余"+this.money);
        }
        else {
            System.out.println("余额不够哦");
        }
 
    }

解决方法三:创建锁对象


作用:可以在指定位置处加锁,解锁,更灵活

final private Lock lk =new ReentrantLock();


lk.lock(); // 加锁


lk.unlock(); // 解锁   一般会放在try...catch finally里

    public  void drawMoney(double money) {
 
        // 先搞清楚是谁来取钱
        String name=Thread.currentThread().getName();
        lk.lock(); // 加锁
        // 判断余额是否足够?
        try {
            if (this.getMoney()>=money){
                System.out.println(name+"取钱成功"+money);
                // 更新余额
                this.money-=money;
                System.out.println(name+"来取钱成功后剩余"+this.money);
            }
            else {
                System.out.println("余额不够哦");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            lk.unlock(); // 解锁
        }
 
    }
目录
相关文章
|
5月前
|
存储 安全 Java
多线程线程安全问题之ThreadLocal是什么,它通常用于什么场景
多线程线程安全问题之ThreadLocal是什么,它通常用于什么场景
|
7月前
|
存储 安全 Java
我们来聊聊线程安全吧
我们来聊聊线程安全吧
|
缓存 安全 Java
认识线程安全和解决线程安全
认识线程安全和解决线程安全
|
安全 Java 编译器
深入理解线程安全
在多线程编程中,线程安全是一个至关重要的概念。线程安全可能到导致数据不一致,应用程序崩溃和其他不可预测的后果。本文将深入探讨线程安全问题的根本原因,并通过Java代码示例演示如何解决这些问题。
147 0
|
安全
KafkaProducer线程安全吗?
KafkaProducer线程安全吗?
|
安全 Java 编译器
关于线程安全问题
关于线程安全问题
107 0
|
存储 安全
什么时候考虑线程安全?
什么时候考虑线程安全?
108 0
|
安全 Java 调度
什么是线程安全的?
首先要明白线程的工作原理,jvm有一个main memory,而每个线程有自己的工作内存,一个线程对一个variable进行操作时,都要在自己的工作内存里面建立一个copy,操作完之后再写入主内存。多个线程同时操作同一个variable,就可能会出现不可预知的结果。
96 0
|
存储 开发框架 算法
线程安全
线程安全
87 0
|
存储 安全 程序员
你管这叫"线程安全"?
今日份的干粮: 1.什么叫线程安全? 2.线程安全与变量的关系? •变量又与堆/栈/静态存储区有密切关系
你管这叫"线程安全"?