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

實際上這就是併發問題,我們需要通過鎖來實現線程安全問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章