• Java多线程-----线程安全


    什么是线程安全

    连个线程同时操作同一个公共资源,容易造成资源错误

    加入两个人代表两个线程他俩同时去取钱10元,但是账户只有10元,如果不处理线程安全容易造成两人都能取出来钱; 

    一,线程同步

    解决线程安全-----加锁

    让多个线程先后依次的访问共享资源


    1,同步代码块

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

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

    • 实现同步代码块

      • 选中共享资源的代码CTRL+T  然后选中 synchronized
        1. //锁对象:必须是一个唯一的对象(同一个地址)锁对象可以是任何对象甚至是字符串
        2. synchronized(锁对象){
        3. //...访问共享数据的代码...
        4. }

    • 对于静态方法建议使用字节码(类名.class对象作为锁对象。
        1. public static void test(){
        2. synchronized(类名.class){
        3. }
        4. }
    • 建议使用共享资源作为锁对象,对于实例方法建议使用this作为锁对象。
      • this 代表着是共享账户
        1. public void test(){
        2. synchronized(this){
        3. }
        4. }

     2,同步方法

    将处理共享资源的方法上加上 syschronized 关键字 表示当前是一个同步方法

    1. public synchronized void drawMoney(double money) {
    2.     // 先搞清楚是谁来取钱?
    3.     String name = Thread.currentThread().getName();
    4.     // 1、判断余额是否足够
    5.     if(this.money >= money){
    6.         System.out.println(name + "来取钱" + money + "成功!");
    7.         this.money -= money;
    8.         System.out.println(name + "来取钱后,余额剩余:" + this.money);
    9.     }else {
    10.         System.out.println(name + "来取钱:余额不足~");
    11.     }
    12. }
    • 如果是实例方法默认使用this作为锁对象
    • 如果是静态方法默认使用类名.class作为锁对象
    • 底层原理:
      • 同步方法其实底层也是有隐式锁对象的,只是锁的范围是整个方法代码

    同步代码块和同步方法的区别

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

    可读性:同步方法更好

    3,Lock锁 

    • 怎么实现

      • 创建锁对象,放在方法外面,表示这个是当前对象的锁  加上final修饰表示当前锁无法被修改
        1. // 创建了一个锁对象
        2. private final Lock lk = new ReentrantLock();
      • 在方法内部需要加锁的地方加锁
      • 在需要的地方进行解锁
      • 以上两步一般使用try-catch-finally修饰,以防中间代码出现问题也能进行解锁

    实现Lock锁

    1. // 创建了一个锁对象
    2. private final Lock lk = new ReentrantLock();
    3. public void drawMoney(double money) {
    4. // 先搞清楚是谁来取钱?
    5. String name = Thread.currentThread().getName();
    6. try {
    7. lk.lock(); // 加锁
    8. // 1、判断余额是否足够
    9. if(this.money >= money){
    10. System.out.println(name + "来取钱" + money + "成功!");
    11. this.money -= money;
    12. System.out.println(name + "来取钱后,余额剩余:" + this.money);
    13. }else {
    14. System.out.println(name + "来取钱:余额不足~");
    15. }
    16. } catch (Exception e) {
    17. e.printStackTrace();
    18. } finally {
    19. lk.unlock(); // 解锁
    20. }
    21. }
    22. }

    注意: 

    同一个锁对象可以跨方法锁住多个方法

  • 相关阅读:
    华为S5700交换机初始化和配置telnet,ssh用户方法
    【前端笔记】Vue + Element UI开发小技巧,持续更新。。。
    用代码实现全自动化批量下单官网的 iPhone-14-Pro 集成智能下单购物系统,附源码可直接运行
    vite 入门到精通
    【uniapp】uniapp开发app在线预览pdf文件
    javaee ssm框架整合例子 ssm例子,需要哪些依赖,配置文件如何配置
    【Datawhale组队学习:Sora原理与技术实战】使用KAN-TTS合成女生沪语音频
    类加载器及反射简单笔记
    【Java SE】面向对象三大特性之多态
    游戏建模‖那些你找工作时不明白的事
  • 原文地址:https://blog.csdn.net/qq_57667629/article/details/134321632