2015-01-12 24 views
2

我正在學習java多線程,並嘗試在JAVA中創建競爭條件。這是我的代碼。如何在JAVA中重新創建競爭條件?

package com.company; 

public class Account { 
    private double balance = 100; 

    public double getBalance() { 
     return balance; 
    } 

    public void setBalance(double balance) { 
     this.balance = balance; 
    } 
    public boolean withdraw(double amount,String name){ 

     if(this.getBalance()>amount){ 
      this.setBalance(this.getBalance() - amount); 
      System.out.println(Thread.currentThread().getName() + " withdraw " + amount); 
      System.out.println("Hello, " + Thread.currentThread().getName() + " You current balance is " + this.getBalance()); 

      return true; 
     } 
     else{ 
      System.out.println("Sorry, " + Thread.currentThread().getName() + ". Your current balance is " + this.getBalance() + " and you cannot withdraw " + amount); 
      //System.out.println("Welcome, " + Thread.currentThread().getName() + " You current balance is " + this.getBalance()); 

      return false; 
     } 
    } 
} 

和主類

package com.company; 
public class Main implements Runnable { 
    Account account = new Account(); 
    public static void main(String[] args){ 
      Main main = new Main(); 
      for(int i= 0; i< 2; i++) { 
       Thread c1 = new Thread(main, "customer" + i); 
       c1.start(); 
      } 
    } 

    @Override 
    public void run() { 
     System.out.println(Thread.currentThread().getName() + "'s balance is " + account.getBalance()); 
     account.withdraw(60, Thread.currentThread().getName()); 
     // 
    } 
} 

Supposingly,這應該產生一個賽車條件下,兩個客戶收回60美元的同時,和爲getBalance()應該告訴我,每個自定義可以撤回60美元,餘額爲每個客戶40美元。但我永遠不能重現這一點。我做錯了什麼?

+0

您可以嘗試使線程停在具有斷點的「關鍵位置」。或者插入線程#睡眠,讓它們在行間慢下來。 – Thilo

+0

另外,如果沒有任何'volatile'或'synchronized',你的類不能保證在多線程之間正確地發佈它的狀態。 – Thilo

+0

你看到任何輸出嗎?你看到了什麼? – Robbert

回答

1

重現競賽條件並不一定容易。它通常取決於線程調度器的時間。

您可以通過你的線程中的一個影響它只是有點睡

if (this.getBalance() > amount) { 
    if (Thread.currentThread().getName().equals("customer0")) 
     try { 
      Thread.sleep(1); // simulates a quicker thread context switch 
     } catch (InterruptedException e) {} 
    this.setBalance(this.getBalance() - amount); 
    System.out.println(Thread.currentThread().getName() + " withdraw " + amount); 
    System.out.println("Hello, " + Thread.currentThread().getName() + " You current balance is " + this.getBalance()); 

    return true; 
} 

注意,即使這不是一個保證。它在我的系統上運行,可能不適用於你的系統。這就是爲什麼競爭條件令人討厭的原因。它們很難一致地重現。

+0

Thanks.I增加了睡眠時間,它工作。 – user454232