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
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:
You start reader1 thread
You start reader2 thread
At some time one of those two threads start. Let's assume reader1 thread starts first:
It syncs to its lock object
It reads a line from the file
It calls its callback, i.e. calls next() on reader1 and reader2. This call is successful (but actually a no-op)
It calls wait on its lock object. And waits...
At some later time the reader2 thread starts
It syncs to its lock object
It reads a line from the file
It calls its callback, however, when calling reader1.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.
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,
Use java.util.CountDownLatch for this problem.
Use ThreadPool. Extending from thread is old way of doing it and prone to errors.
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.
Related
I'm curious to submit here a short example I made and hopefully have someone able to explain to me one thing: is it possible to use the wait() and notify() inside a synchronized block without having to declare threads explicitly? (AKA: not using dedicated threads).
Here's the example:
public class mutex {
private Object mutex = new Object();
public mutex(Object mutex) {
this.mutex = mutex;
}
public void step1() throws InterruptedException {
System.out.println("acquiring lock");
synchronized(mutex) {
System.out.println("got in sync block");
System.out.println("calling wait");
mutex.wait();
System.out.println("wait finished ");
}
}
public void step2() throws InterruptedException{
System.out.println("acquiring lock");
synchronized(mutex){
System.out.println("got in sync block");
System.out.println("calling notify");
mutex.notify();
System.out.println("notify called");
}
}
Those two simple step are just prints for logging and what should be happening.
The idea is to be able to call a wait() in step1 and be able to complete the call once step2 has been called with its notify().
Now, as far as I understood the whole thing, this is the right way to do what I want to do:
public void go1() {
Object mutex = new Object();
mutex m = new mutex(mutex);
Thread t1 = new Thread(()->{
try {
m.step1();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(()->{
try {
Thread.sleep(1000);
m.step2();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
}
and finally the main
public static void main(String[] args) {
Object mutex = new Object();
new mutex(mutex).go1();
//new mutex(mutex).go2();
}
The above code works and shows what I am expecting:
acquiring lock
got in sync block
calling wait
acquiring lock
got in sync block
calling notify
notify called
wait finished
I get why it works. This is what I expected to happen and how I have been taught to do this. The question comes now as I will paste the second variant of the main function I wanted to test - this one just hangs when the wait() is called.
public void go2() {
Object mutex = new Object();
mutex m = new mutex(mutex);
try {
m.step1();
Thread.sleep(1000);
m.step2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Why does this hang?
Is it because there is just one thread doing everything and it goes into waiting state after the wait() is called?
I know that when wait is called on the monitor object it should also release the lock, so why in this case the program can't get to call the step2()?
Is there a way to use the my second go() function to achieve this process or is it impossible for it to work?
TLDR just so I am making sure I can be understood: do I have to use dedicated threads to also use properly wait() and notify()? Because I seem to get deadlocks if I don't.
Thank you.
Once you call mutex#wait, the current thread is added to the wait set of object mutex. And thread will not execute any further instructions until it has been removed from mutex's wait set. That's why step2 cannot be executed by the current thread.
The current thread will be removed from the wait set and resume if other threads call mutex#notify/notifyAll. See JLS#WAIT for all situations in which the current thread can resume..
I've a situation where I need to implement a thread safe method, The method must be executed by only one thread at a time, And while the method is being executed by a thread, all other threads trying to execute the same method shouldn't wait and must exit the method.
Synchronization won't help here since threads will be waiting to execute the method sequentially.
I thought I would achieve this by making use of ConcurrentHashMap using below code, but not sure if this is the perfect way to implement it.
Class Test {
private ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();
public void execute() {
if (map.putIfApsent("key", new Object()) != null) { // map has value for key which means a thread has already entered.
return; // early exit
}
threadSafeMethod();
map.remove("key");
}
private void threadSafeMethod() {
// my code
}
}
You can do this without synchronization, with compare-and-swap using a boolean:
private AtomicBoolean entered = new AtomicBoolean(false);
public void execute() {
if(entered.compareAndSet(false,true) {
try {
method()
} finally {
entered.set(false)
}
}
}
You could use a ReentrantLock and specify a negative value for waiting time. In that case the scheduler will not try to wait if there is a thread already executing the code.
// define the lock somewhere as an instance variable
Lock lock = new ReentrantLock();
try {
var isAvailable = lock.tryLock(-1, TimeUnit.NANOSECONDS);
if(isAvailable) {
System.out.println("do work");
lock.unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
Class clazz has two methods methodA() and methodB().
How to ensure that methodB is "blocked" if some threads are in methodA in Java (I am using Java 8)?
By "blocking methodB", I mean that "wait until no threads are in methodA()". (Thanks to #AndyTurner)
Note that the requirement above allows the following situations:
Multiple threads are simultaneously in methodA.
Multiple threads are in methodB while no threads are in methodA.
Threads in methodB does not prevent other threads from entering methodA.
My trial: I use StampedLock lock = new StampedLock.
In methodA, call long stamp = lock.readLock()
Create a new method unlockB and call lock.unlockRead(stamp) in it.
In methodB, call long stamp = lock.writeLock() and lock.unlockWrite(stamp).
However, this locking strategy disallows the second and the third situations above.
Edit: I realize that I have not clearly specified the requirements of the synchronization between methodA and methodB. The approach given by #JaroslawPawlak works for the current requirement (I accept it), but not for my original intention (maybe I should first clarify it and then post it in another thread).
I think this can do the trick:
private final Lock lock = new ReentrantLock();
private final Semaphore semaphore = new Semaphore(1);
private int threadsInA = 0;
public void methodA() {
lock.lock();
threadsInA++;
semaphore.tryAcquire();
lock.unlock();
// your code
lock.lock();
threadsInA--;
if (threadsInA == 0) {
semaphore.release();
}
lock.unlock();
}
public void methodB() throws InterruptedException {
semaphore.acquire();
semaphore.release();
// your code
}
Threads entering methodA increase the count and try to acquire a permit from semaphore (i.e. they take 1 permit if available, but if not available they just continue without a permit). When the last thread leaves methodA, the permit is returned. We cannot use AtomicInteger since changing the count and acquiring/releasing permit from semaphore must be atomic.
Threads entering methodB need to have a permit (and will wait for one if not available), but after they get it they return it immediately allowing others threads to enter methodB.
EDIT:
Another simpler version:
private final int MAX_THREADS = 1_000;
private final Semaphore semaphore = new Semaphore(MAX_THREADS);
public void methodA() throws InterruptedException {
semaphore.acquire();
// your code
semaphore.release();
}
public void methodB() throws InterruptedException {
semaphore.acquire(MAX_THREADS);
semaphore.release(MAX_THREADS);
// your code
}
Every thread in methodA holds a single permit which is released when the thread leaves methodA.
Threads entering methodB wait until all 1000 permits are available (i.e. no threads in methodA), but don't hold them, which allows other threads to enter both methods while methodB is still being executed.
You can't really prevent that methodA or methodB is called (while other threads are inside the other method) but you can implement thread intercommunication in such a way so that you can still achieve what you want.
class MutualEx {
boolean lock = false;
public synchronized void methodA() {
if (lock) {
try {
wait();
}catch (InterruptedException e) {
}
}
//do some processing
lock = true;
notifyAll();
}
public synchronized void methodB() {
if (!lock) {
try {
wait();
}catch (InterruptedException e) {
}
}
//do some processing
lock = false;
notifyAll();
}
}
Now, for this to work any Thread object you create should have a reference to the same instance of MutualEx object.
Why not using an kind of external orchestrator?
I mean another class that will be responsible to call the methodA or methodB when it allowed.
Multi-thread can still be handle via locking or maybe just with some AtomicBoolean(s).
Please find below a naive draft of how to do it.
public class MyOrchestrator {
#Autowired
private ClassWithMethods classWithMethods;
private AtomicBoolean aBoolean = = new AtomicBoolean(true);
public Object callTheDesiredMethodIfPossible(Method method, Object... params) {
if(aBoolean.compareAndSet(true, false)) {
return method.invoke(classWithMethods, params);
aBoolean.set(true);
}
if ("methodA".equals(method.getName())) {
return method.invoke(classWithMethods, params);
}
}
}
In very simple terms what you all need is ENTER methodB only if no thread inside methodA.
Simply you can have a global counter, first initialized to 0 to record the number of threads that are currently inside methodA(). You should have a lock/mutex assigned to protect the variable count.
Threads entering methodsA do count++.
Threads exiting methodA do count-- .
Threads that are entering methodB first should check whether count == 0.
methodA(){
mutex.lock();
count++;
mutex.signal();
//do stuff
mutex.lock();
count--;
mutex.signal();
}
methodB(){
mutex.lock();
if(count != 0){
mutex.signal();
return;
}
mutex.signal();
//do stuff
}
You would need an int to count threads in methodA, and ReentrantLock.Condition to signal all threads waiting in methodB once there are no threads in methodA:
AtomicInteger threadsInMethodA = new AtomicInteger(0);
Lock threadsForMethodBLock = new ReentrantLock();
Condition signalWaitingThreadsForMethodB = threadsForMethodBLock.newCondition();
public void methodA() {
threadsInMethodA.incrementAndGet();
//do stuff
if (threadsInMethodA.decrementAndGet() == 0) {
try {
threadsForMethodBLock.lock();
signalWaitingThreadsForMethodB.signalAll();
} finally {
threadsForMethodBLock.unlock();
}
}
}
public void methodB() {
try {
threadsForMethodBLock.lock();
while (!Thread.isInterrupted() && threadsInMethodA.get() != 0) {
try {
signalWaitingThreadsForMethodB.await();
} catch (InterruptedException e) {
Thread.interrupt();
throw new RuntimeException("Not sure if you should continue doing stuff in case of interruption");
}
}
signalWaitingThreadsForMethodB.signalAll();
} finally {
threadsForMethodBLock.unlock();
}
//do stuff
}
So each thread entering methodB will first check if nobody in methodA, and signal previous waiting threads. On the other hand, each thread entering methodA will increment counter to prevent new threads doing work in methodB, and on decrement it will release all the threads waiting to do stuff in methodB if no threads left inside methodA.
I have three classes, one that is meant to represent a pile of urls
private Queue<String> queue = new LinkedList<String>();
public Queue<String> getQueue() {
return queue;
}
private int limit = 5;
private int stillParsing;
public synchronized String getNextString() throws InterruptedException {
while (queue.isEmpty()||stillParsing > limit) {
System.out.println("no for you "+ queue.peek());
wait();
}
System.out.println("grabbed");
notify();
stillParsing++;
System.out.println(queue.peek());
return queue.remove();
}
public synchronized void doneParsing() {
stillParsing--;
}
}
A thread class whose run method is
public void run(){
try {
sleep(30);
for(;;){
String currenturl = pile.getNextString();
//(do things)
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
pile.doneParsing();
}
}
And a mapper that actually adds objects into the pile of urls using this snipet
while (urls.hasMoreTokens()) {
try{
word.set(urls.nextToken());
String currenturl = word.toString();
System.out.println(currenturl);
pile.getQueue().add(currenturl);
From debugging what I think happens is that all of the threads try to get from the queue at once before the mapper has a chance to populate it and they get stuck waiting. Unfortunately all of the threads waiting is causing my program to hang up and not add more urls to the queue. How should I go about taking care of this issue? Preferably while still using wait notify.
while (urls.hasMoreTokens()) {
try {
word.set(urls.nextToken());
String currenturl = word.toString();
System.out.println(currenturl);
pile.getQueue().add(currenturl);
In the above code, you're breaking the encapsulation of the pile by adding something to its queue without going though a method of the pile. You should not have a getQueue() method in this class: all the accesses to this shared data structure should be synchronized on the same lock. You should thus add a synchronized method allowing to add a URL to the queue. And this method should also call notify() (or better: notifyAll()), in order to wake up the threads that are waiting for some element to be in the queue:
public synchronized void addUrl(String url) {
queue.add(url);
notifyAll();
}
Even without reading all lines of your code and explanations I can say that your usage of wait and notify are buggy.
Method wait() is blocking. It exits only when notify() on the same monitor is called. This means that you cannot put both wait() and notify() from the same thread. You simply never arrive to notify() because wait() is blocked forever.
Other version of wait(): wait(timeout) is blocked but is limited by specified timeout.
Moreover wait/notify pair work only if they are written into synchronized block:
// thread-1
synchronoized(obj) {
obj.wait();
}
// thread-2
synchronoized(obj) {
obj.notify();
}
Thread-1 will exit wait when thread-2 calls notify.
I have a method and a thread which I'd like to run in the following order: First the method should do something with an object, and then the thread should do something with the object. They share the same object. I have to synchronize them, but I am just meeting with Threads. How can I do that?
private synchronized method()
{
//do something with an object (a field)
}
Runnable ObjectUpdater = new Runnable()
{
//do something with the object after the method has finished
}
My code, that somehow manages to freeze my Main thread (where the method is)
My thread code:
private Runnable something = new Runnable(){
synchronized (this){
while (flag == false)
{ try {wait();)
catch (IntExc ie) {e.printStackTrace...}
}
//here it does its thing
}
setFlag(false);
}
My method code (part of the main thread)
private void Method()
{
//do its thing
setFlag(true);
notifyAll();
}
To me that is simple questions
" you said that I do not know which is
going to access the object first - the
separate ObjectUpdater thread, or the
main thread (with the method). If the
separate thread accesses it before the
main thread, that is bad and I don't
want this to happen"
if you want the main thread method to call first then the objectUpdater thread , have a flag to know whether the method is visited first by main thread ,if it is updater then call wait to this thread , once main finishes it call notify which will run separator thread,
to know which thread is main thread or updater thread , set a name to the thread while creating it. and get the name as Thread.currentThread().getName().
Use the Semaphore class to allow access to the object.
public class Main
{
public static void main (String[] args) {
final Obj obj = new Obj();
final Semaphore semaphore = new Semaphore(0);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
semaphore.acquire();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
return;
}
obj.doSomething();
}
});
t.setName("test");
t.start();
try {
Thread.sleep(1000);
} catch (InterruptedException ignored) {
}
obj.doSomething();
semaphore.release();
}
}
class Obj {
public void doSomething() {
System.out.println("something done by " + Thread.currentThread());
}
}
Apart from synchronizing on the object, you could call the method as first statement in the new thread, or you could start the new thread at the end of the method.
It is hard to say what is the best approach in your case, maybe you can give us some more details on the how and what?
Update
In answer to your code (for some reason I cannot add another comment...)
Is the method called from a synchronized(this) block? If not the notifyAll() should be in a synchronized block. Also, can you update the code to show where/how your main thread interacts with the method and the object?
I think better approach would be to call the method using which you want to perform something with an object, and then declare the thread which would do something with an object.