2012-04-04 38 views
0

我無法理解爲什麼我在這個簡單的示例中陷入僵局。它有什麼問題?爲什麼我會陷入僵局

public static void main(String[] args) { 
     Object data = null; 
     new Thread(new Producer(data)).start(); 
     new Thread(new Consumer(data)).start(); 
    } 
} 

class Producer implements Runnable { 
    private Object data; 

    public Producer(Object data) { 
     this.data = data; 
    } 

    @Override 
    public void run() { 
     while (true) { 
      while (data != null) {} 
      data = new Object(); 
      System.out.println("put"); 
     } 
    } 
} 

class Consumer implements Runnable { 
    private Object data; 

    public Consumer(Object data) { 
     this.data = data; 
    } 

    @Override 
    public void run() { 
     while (true) { 
      while (data == null) { } 
      data = null; 
      System.out.println("get"); 
     } 
    } 
+0

這麼多層面上都是錯誤的。 – SLaks 2012-04-04 17:44:18

回答

1

當您生產的「生產」時,它所做的只是指向它自己的data對新對象的引用,並且消費者無法知道發生了什麼。你可以做的卻是讓其他類

class Data { 
    private Object data = null; 
    synchronized void set(Object data){ this.data = data; } 
    synchronized Object get(){ return data; } 
} 

然後在你的主做

Data data = new Data(); 

傳遞「數據」對象,以消費者和生產者,並使用get/set方法,而不是分配。

這樣,消費者和生產者都將指向同一個對象,當生產者生產或消費者消費時,他們將改變他們共享的數據對象中的引用。

2

每個實例都有自己的data字段。
消費者從未看到生產者的變化。

2

消費者和生產者有單獨的數據字段,所以消費者永遠不會得到任何數據消費。

此外,在現場spinlocking消費者/生產者是不是一般的好主意,你最好使用互斥或​​信號量信號數據的可用性/可能性進行發佈。如果這不僅僅是尋找知識的考驗,你應該真正瞭解如何使用這兩種知識。

3

有兩個問題。

1:您有兩個單獨的Runnable,每個Runnable都有自己的私有內部成員,名爲data。對其中一個進行的更改對另一個不可見。如果你想在兩個線程之間傳遞數據,你需要將它存儲在一個共同的地方,他們都可以訪問它。您還需要在訪問周圍同步或使參考變得不穩定。

2:您的支票似乎倒過來。當它不爲null時,你可能想要將它清空,並且當它爲空時創建一個?它很難說出你想要它在那裏實際做什麼! :)

public static volatile Object data; 

public static void main(String[] args) { 
     data = null; 
     new Thread(new Producer(data)).start(); 
     new Thread(new Consumer(data)).start(); 
    } 
} 

class Producer implements Runnable { 

    public Producer(Object data) { 
     this.data = data; 
    } 

    @Override 
    public void run() { 
     while (true) { 
      while (data == null) {} 
      data = new Object(); 
      System.out.println("put"); 
     } 
    } 
} 

class Consumer implements Runnable { 

    public Consumer(Object data) { 
     this.data = data; 
    } 

    @Override 
    public void run() { 
     while (true) { 
      while (data != null) { } 
      data = null; 
      System.out.println("get"); 
     } 
    } 

(另外這是不是一個真正的經典例子我們會定義爲死鎖,兩個線程無法繼續,因爲他們都希望鎖定其他了。這裏沒有鎖。這是兩個無限循環的例子,它們只是不做任何事情。)

1

我想這應該做你想要什麼(它仍然是錯誤代碼):

public class Example { 
    public static void main(String[] args) { 
     Consumer consumer = new Consumer(); 
     new Thread(new Producer(consumer)).start(); 
     new Thread(consumer).start(); 
    } 
} 

class Producer implements Runnable { 
    private final Consumer consumer; 

    public Producer(Consumer consumer) { 
     this.consumer = consumer; 
    } 

    @Override 
    public void run() { 
     while (true) { 
      while (consumer.data != null) {} 
      consumer.data = new Object(); 
      System.out.println("put"); 
      try { 
       Thread.sleep(5); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

class Consumer implements Runnable { 
    public volatile Object data; 

    @Override 
    public void run() { 
     while (true) { 
      while (data == null) {} 
      data = null; 
      System.out.println("get"); 
      try { 
       Thread.sleep(5); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

我想你應該專注於Java基礎,你去學習高級主題之前,如並行編程的示例中的主要錯誤(單獨的數據字段)非常基本。