多线程之对象及变量的并发访问(二) - 实例变量非线程安全

一、前述

本文继续分享多线程的对象及变量的并发访问

二、实例变量非线程安全

平时开发中,经常会遇到多个线程共同访问一个实例变量,这样就会出现非线程安全的脏读问题
线程访问的对象中,如果有多个实例变量,那么运行的结果可能就是会出现交叉运行,如果只有一个实例变量,可能出现被后来的覆盖的现象
接下来看看 demo:

public class SynTestA {
    private int num = 0;
    public void addA(String name){
       try {
           if(name.equals("a")){
               num = 100;
               System.out.println("a set over");
               Thread.sleep(2000);
           }else{
               num = 200;
               System.out.println("b set over");
           }
           System.out.println(name + " num = " + num);
       }catch (InterruptedException e){
           e.printStackTrace();
       }
   }

}
public class ThreadA extends Thread{
    private SynTestA synTestA;
    public ThreadA(SynTestA synTestA){
        super();
        this.synTestA = synTestA;
    }
    @Override
    public void run(){
        super.run();
        synTestA.addA("a");

    }
}

public class ThreadB extends Thread{
    private SynTestA synTestA;
    public ThreadB(SynTestA synTestA){
        super();
        this.synTestA = synTestA;
    }
    @Override
    public void run(){
        super.run();
        synTestA.addA("b");

    }
}
public class Run {
    public static void main(String[] args) {
        SynTestA synTestA = new SynTestA();
        ThreadA threadA = new ThreadA(synTestA);
        threadA.start();
        ThreadB threadB = new ThreadB(synTestA);
        threadB.start();
    }
}
运行结果:
a set over
b set over
b num = 200
a num = 200

上述代码就是两个线程同时一个没有同步的方法,两个线程并发同时对业务对象中的实例变量 num 操作的时候,就出现了非线程安全的问题,这里原本应该是 a set over,a num = 100,但是由于并发,a 线程跑到一半的时候,b 线程进入了这个方法,并且将实例变量 num 修改为了 200,b 线程结束以后,a 还在继续跑,此时读取到了 num = 200,所以就出现了所谓的数据脏读,要使程序按照正确的逻辑运行,只需要对方法 addA 前面加上关键字 synchronized 就可以保证不出现数据脏读,如下:

public class SynTestA {
    private int num = 0;
    public synchronized void addA(String name){
       try {
           if(name.equals("a")){
               num = 100;
               System.out.println("a set over");
               Thread.sleep(2000);
           }else{
               num = 200;
               System.out.println("b set over");
           }
           System.out.println(name + " num = " + num);
       }catch (InterruptedException e){
           e.printStackTrace();
       }
   }
}
运行结果:
a set over
a num = 100
b set over
b num = 200

将方法改为同步以后,两个线程访问同一个对象中的同步方法时一定是线程安全的,同步访问,所以先打印 a ,再打印 b

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值