天天看點

一把鎖引發的問題,synchronized方法與非synchronized方法共存産生資料髒讀問題

模拟場景:

寫一段小程式,一個方法給某人賬戶充值,另一個方法查詢某人的賬戶,如果兩個方法都不加鎖,并發情況下肯定會問題,現在隻給充值方法加鎖,查詢方法不加,由于synchronized與非synchronized方法可以同時運作,是以查詢方法可能産生髒讀問題。

public class Account {


    String name;
    double balance;

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

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

        this.balance = balance;


    }

    public double getBalance(String name) {
        if (name.equals(this.name)) {
            return this.balance;
        }
        return 0.0;
    }

    public static void main(String[] args) throws InterruptedException {
        Account acc = new Account();
        new Thread(() -> acc.setBalance("張三", 100)).start();

        TimeUnit.SECONDS.sleep(1);//暫停1秒

        /**
         * setBalance還未執行完成,讀到的還是balance的預設值,即0.0,也就是髒讀
         */
        System.out.println(acc.getBalance("張三"));

        TimeUnit.SECONDS.sleep(2);//再暫停3秒

        /**
         * setBalance已執行完成,讀到的是balance的最新值,即100.0
         */
        System.out.println(acc.getBalance("張三"));

    }

}      

結果

0.0

100.0

 是否需要給讀方法同時加上synchronized?看需求,如果需求場景允許出現髒讀(僅僅是讀,不進行任何寫操作),可以不用加,加上synchronized性能将急劇下降,如果場景不允許髒讀,該加還是要加。

public synchronized double getBalance(String name) {
        if (name.equals(this.name)) {
            return this.balance;
        }
        return 0.0;
    }      
public double getBalance(String name) {
        synchronized (this) {
            if (name.equals(this.name)) {
                return this.balance;
            }
            return 0.0;
        }
    }      
public static synchronized void fun(){
        // to do something
    }

 //等價于
 public static  void fun(){

       synchronized(Account.class){
            // to do something
       }
   }