thread06 - 读写加锁

package com.neutron.t06;

import java.util.concurrent.TimeUnit;

/**
 * 对业务写方法加锁,对业务对方法不加锁,容易产生脏读现象
 */
public class T06 {
    String name;
    double balance;

    public synchronized void set(String name, double balance) {
        this.name = name;

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        this.balance = balance;
    }

    public /*synchronized*/ double getBalance(String name) {
        return balance;
    }

    /**
     * 分析执行思路:
     *    1.创建对象执行set方法时,name赋值后睡上2秒,此时balance等于0.0
     *    2.主线程睡1秒
     *    3.打印boss的账户,此时set方法才睡1秒,并没有执行balance赋值,此时balance等于0.0
     *    4.主线程睡2秒,此时set方法睡过了2秒,balance已经赋值为2000
     *    5.打印boss的账户,此时balance是2000
     */
    public static void run2() {
        T06 t06 = new T06();
        new Thread(() ->t06.set("boss", 2000)).start();

        try {
            TimeUnit.SECONDS.sleep(1);
            // 作用类似于:Thread.sleep(1);是对Thread.sleep的进一步封装,可读性良好
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(t06.getBalance("boss"));

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(t06.getBalance("boss"));
    }

    /*
        运行结果:
            0.0
            2000.0
     */
    public static void main(String[] args) {
        run2();
    }
}

/*
    过程解说:
    1.在写的过程中锁,但获取方法不锁定,那么在写的过程中,调用了不锁定的读方法
      即在set方法中name和balance之间执行get方法,返回的balance值是0
    2.解决方案是读写方法都加锁,并且使用的是同一把锁,目前都是this。
      get方法中将注释内容synchronized取消即可。
 */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值