Reputation: 681
I have a FileReader class which is like this
public class FileReader extends Thread
{
private final Object lock = new Object();
public FileReader(String path, FileReaderCallback callback)
{
super(path);
this.path = path;
this.callback = callback;
}
@Override
public void run()
{
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
String info;
while ((info = reader.readLine()) != null)
{
synchronized (lock)
{
callback.onDone(path, info);
try
{
lock.wait();
}
catch (Exception ignored)
{
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void next()
{
synchronized (lock)
{
try
{
lock.notify();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
And I have two instance of this FileReader because I want to read two file line by line simultaneously. The problem is my code only reads one line from both file and then it's going to pause.
I Call the function on my callback like this
public void onDone(String path, String info)
{
reader1.next();
reader2.next();
}
So what's the problem?!
Thanks in advance
Upvotes: 0
Views: 410
Reputation: 1169
You are facing a classic deadlock scenario. Let the first lock be lock1
and the second lock be lock2
. In your first instance, the lock status can be expressed as follows:
synchronized (lock1) {
// start of onDone
synchronized (lock1) {
}
synchronized (lock2) {
}
// end of onDone
}
and in second one, it is like this:
synchronized (lock2) {
// start of onDone
synchronized (lock1) {
}
synchronized (lock2) {
}
// end of onDone
}
You should refine your logic, as other answers suggest.
Another flaw in your design is; you are also not considering possible spurious wakeups. Generally, you should put your wait()
calls in a while
loop.
Upvotes: 0
Reputation: 2575
Your lock
object which you synchronize the next()
method to is also used within your while
loop in the run
method. Therefore, the code of your next()
method cannot be called from within another thread.
Just assume the following program flow:
reader1
threadreader2
threadAt some time one of those two threads start. Let's assume reader1
thread starts first:
lock
objectnext()
on reader1
and reader2
. This call is successful (but actually a no-op)wait
on its lock
object. And waits...At some later time the reader2
thread starts
lock
objectreader1.next()
it tries to synchronize to the reader1
its lock
object from a different thread, thus putting your program into a deadlock state.To solve this problem I would really suggest to overwork the concept of how you perform the line-by-line synchronization. An easy fix would probably be to use a different lock variable for your next()
method.
Upvotes: 1
Reputation: 2262
You are calling listener call back while holding the lock on the same object lock
. This will allow notify to be invoked before a wait is invoked. This will make your thread wait forever.
You should,
Upvotes: 0