Reputation: 735
I cannot understand why I am getting deadlock in this simple sample.What is wrong with it?
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");
}
}
Upvotes: 0
Views: 100
Reputation: 1276
I think this should do what you intend (it is still bad code):
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();
}
}
}
}
I think you should focus on the basics of Java, before you go for advanced topics such as parallel programming as the main error in you example (separate data fields) is very basic.
Upvotes: 1
Reputation: 23455
When your produced "produces", all it does is points its own data
reference to the new object, and the consumer has no way of knowing what happened. What you can do instead is make another class
class Data {
private Object data = null;
synchronized void set( Object data ){ this.data = data; }
synchronized Object get(){ return data; }
}
Then in your main do
Data data = new Data();
Pass the 'Data' object to the consumer and producer, and use the get/set methods instead of assignment.
That way, both consumer and producer will be pointing to the same Data
object and when the producer produces or the consumer consumes, they will be changing the reference in the Data object, which they are sharing.
Upvotes: 1
Reputation: 180877
The consumer and producer have separate data fields, so the consumer will never get any data to consume.
Also, spinlocking a consumer/producer on a field isn't generally a good idea, you're much better off using mutexes or semaphores to signal the availability of data / the possibility to publish. If this is more than a test in the search of knowledge, you should really read up on how to use those two.
Upvotes: 2
Reputation: 47954
There are two problems.
1: You have two separate Runnables that each have their own private internal member named data. Changes made to one aren't visible to the other. If you want to pass data between two threads, you need to store it in a common place where they both access it. You also need to either synchronize around the accesses or make the reference volatile.
2: Your checks seem to be inverted. You probably want to null it when it's not null, and create one when it is null? Its tough to tell what you want it to actually do there! :)
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");
}
}
(Also this isn't really an example classically what we'd define as a deadlock, where two threads can't proceed because they both want locks the other has. There are no locks here. This is an example of two infinite loops that just don't do anything.)
Upvotes: 3
Reputation: 887245
Each instance has its own data
field.
The consumer never sees the producer's changes.
Upvotes: 2