1.8 模拟脏读(dirtyRead)问题

2019-03-02  本文已影响0人  殊胜因缘_Chris
/**
 * This is description.
 * 模拟脏读(dirtyRead): 对业务写方法加锁, 对业务读方法不加锁, 可能会出现脏读.
 *
 * @author Chris Lee
 * @date 2019/3/2 16:29
 */
public class Account {
    String name;
    double balance;

    /**
     * 写方法进行加锁, 设置账户名和余额.
     *
     * @param name
     * @param balance
     */
    public synchronized void setAccount(String name, double balance) {
        this.name = name;

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

        this.balance = balance;
    }

    /**
     * 读方法: 获取账户余额.
     * 加锁就避免了脏读, 为什么?
     * 原因:
     * 对非静态方法加锁实质上是锁定了堆中的对象, 写和读方法同时加锁, 那么读方法就必须等待写方法的锁释放之后(此时name和balance均赋值成功),
     * 才能获得该对象锁, 从而避免了脏读.
     * @return
     */
    public /*synchronized*/ double getBalance() {
        return this.balance;
    }

    public static void main(String[] args) {
        Account account = new Account();
        new Thread(() -> account.setAccount("Chris", 100.0)).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("the balance of Chris is : " + account.getBalance());

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("the balance of Chris is : " + account.getBalance());

        /*
        读方法不加锁:
            the balance of Chris is : 0.0(脏读产生)
            the balance of Chris is : 100.0
        读方法加锁:
            the balance of Chris is : 100.0
            the balance of Chris is : 100.0
         */
    }

}
说明:
资料:
  1. 学习视频: https://www.bilibili.com/video/av11076511/?p=1
  2. 参考代码: https://github.com/EduMoral/edu/tree/master/concurrent/src/yxxy
  3. 我的代码: https://github.com/ChrisLeejing/learn_concurrency.git
上一篇下一篇

猜你喜欢

热点阅读