JAVA多线程-数据脏读

多线程数据脏读实际上我们在前面已经遇到过了,就是前面同一个对象持有一把锁比较类锁,我们先看下脏读的情况:

账户类:

package com.ck.thread;

import java.math.BigDecimal;

package com.ck.thread;

import java.math.BigDecimal;

public class Account {


    private String name;


    private BigDecimal balance = new BigDecimal("0");



    public String getName() {

        return name;

    }



    public void setName(String name) {


        this.name = name;


    }



    public BigDecimal getBalance() {

        return balance;

    }


    public void setBalance(BigDecimal balance) {

        this.balance = balance;

    }


    public synchronized void add(BigDecimal amount) {

        System.out.println(name + ", 开始充值,充值前余额: " + balance);

        try {


            Thread.sleep(2000);

            balance = balance.add(amount);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println(name + ", 结束充值,充值后余额: " + balance);

    }


    public  void print() {

        System.out.println(name + ", 当前余额: " + balance);

    }

}

 

我们在写个充值的线程类:

package com.ck.thread;


import java.math.BigDecimal;

public class CzThread extends Thread{



    private Account account;

   
    public CzThread(Account account) {

        this.account = account;
    }

   
    @Override

    public void run() {

        account.add(new BigDecimal("100"));

    }


    public Account getAccount() {

        return account;

    }



    public void setAccount(Account account) {

        this.account = account;

    }

}

查询余额:


package com.ck.thread;

public class PrintThread extends Thread{


    private Account account;


    public PrintThread(Account account) {

        this.account = account;

    }



    @Override

    public void run() {

        account.print();

    }


    public Account getAccount() {

        return account;

    }


    public void setAccount(Account account) {

        this.account = account;

    }


}

用户先充值再查询余额:

package com.ck.thread;


import java.math.BigDecimal;

public class MainThread {


    public static void main(String[] args) throws InterruptedException {

        Account account1 = new Account();

        account1.setName("张三");

        account1.setBalance(new BigDecimal("100"));

        Thread t1 = new CzThread(account1);

        t1.start();

        Thread.sleep(500);

        Thread t2 = new PrintThread(account1);

        t2.start();

    }

}

看下结果:

张三, 开始充值,充值前余额: 100



张三, 当前余额: 100



张三, 结束充值,充值后余额: 200

这时候就出现了脏数据,因为余额应该是200,我们修改下:

package com.ck.thread;

import java.math.BigDecimal;


public class Account {


    private String name;


    private BigDecimal balance = new BigDecimal("0");


    public String getName() {

        return name;
    }



    public void setName(String name) {

        this.name = name;

    }


    public BigDecimal getBalance() {

        return balance;

    }



    public void setBalance(BigDecimal balance) {

        this.balance = balance;

    }


    public synchronized void add(BigDecimal amount) {

        System.out.println(name + ", 开始充值,充值前余额: " + balance);

        try {


            Thread.sleep(2000);

          balance = balance.add(amount);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println(name + ", 结束充值,充值后余额: " + balance);

    }


    /**注意这儿加锁了*/

    public synchronized void print() {

        System.out.println(name + ", 当前余额: " + balance);

    }

}

我们将获取余额也加锁了,我们看下运行结果:

张三, 开始充值,充值前余额: 100



张三, 结束充值,充值后余额: 200



张三, 当前余额: 200

实际上这就是并发问题,我们需要通过锁来实现线程安全问题。

猜你喜欢

转载自blog.csdn.net/cgsyck/article/details/106196487