2012-04-04 36 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基础,你去学习高级主题之前,如并行编程的示例中的主要错误(单独的数据字段)非常基本。