多线程的脏读问题

脏读

脏读:多个线程共享资源调,一些线程还在进行写入修改操作,而另外一些线程读取到了尚未写入完成可能进行事务回滚的数据。

class User {
    private String username = "A";
    private String password = "AA";
    synchronized public void setValue(String use, String pwd){
        try {
        //可能会进行事务的回滚,即写入数据不成功还是原来的值。
            this.username = use;
            Thread.sleep(5000);
            this.password = pwd;
            System.out.println(Thread.currentThread().getName() + ": " + username + " " + password);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void getValue(){
        System.out.println(Thread.currentThread().getName() + ": " + username + " " + password);
    }
}

class userA extends Thread{

    private User use;

    userA(User use,String name){
        super(name);
        this.use = use;
    }

    @Override
    public void run() {
        use.setValue("Splay","Treap");
    }
}

class userB extends Thread{

    private User use;

    userB(User use,String name){
        super(name);
        this.use = use;
    }

    @Override
    public void run() {
        use.getValue();
    }
}

public class Test {
    public static void main(String[] args) {
        User user = new User();

        userA a = new userA(user,"A");
        userB b = new userB(user,"B");

        a.start();
        b.start();
        /*
            脏读: A线程修改数据未完成时,B读到了A没有成功提交的数据。
            sychronized只同步了setValue方法,并没有同步getValue方法。
            此时A线程和B线程可以形成异步访问,A虽然拿到了实例化对象User的对象锁,
            但是对象锁只锁了所有的同步方法,对于非同步方法并没有锁住。
            所以B会脏读到A未提交的数据。解决方法就是将getValue方法变为同步方法。
         */
    }
}

在这里插入图片描述

分析:最开始的username = “A”, password = “AA”。此时A线程先去修改用户名和密码,但是此时没有修改完成被B读取到了这些尚未完成提交的数据。但是A线程具体能否成功写入当前数据按照业务顺序来说是无法判断的。所以B读取到的username = "Spaly"是一个脏数据。解决方法就是将getValue方法也使用synchronized关键词进行同步。

结论: 这也从侧面反应出当多个线程共享一个实例化对象时,synchronized方法和普通方法是可以异步访问的;即一个线程抱到对象锁后,其他线程继续访问该对象的其他synchronized方法需要同步,但是可以通过异步的方式访问该对象的其他非synchronized的方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值