Hi I'm pretty new to Java and now I'm getting into java concurrency. And I have a little doubt about Synchronized methods: i have seen that I can get the same results using an If else inside a Synchronized method, checking every time If the condition to do an action is fullfilled, as using a wait / notify approach.
Since i get the same result I'm wondering If the If else approach has any advantages or disadvantages over t'he wait and notify approach? I supose that efficiency will be a disadvantage, since If is always checking the condition, Who le wait Just stops and waits for notify. But are any other advantages or disadvantages?
Thx!
You are mixing two concepts. If-Else vs Wait-Notify are totally different. You want two threads to communicate with each-other that is where Wait-Notify would be used while if-else is general conditional statement.
You cannot have two threads communicate with each other simply using if-else condition. You can write your code that makes it look like it does however you are simply not allowing threads to interact with each other.
Moreover it can lead to undesirable consequences/computational states. Sooner or later you would have hotchpotch code.
synchronized block makes the code thread safe. You would want to use wait() and notify() or notifyAll() if you want to be more efficient.
For example if your shared resource is a list, multiple threads share. If you put it in synchronized block of a monitor then threads will constantly jump in and run the code, during context switches. Even if the list is enpty!!
The wait() is hence used on the monitor (the object inside the synchronized(..)) as a mechanism to 'tell' all threads to chill out and stop using CPU cycles until further notice or notifyAll().
synchronized(monitor) {
while( list.isEmpty() )
monitor.wait();
doSomething(...)
}
In the above example, doSomething() will be executed only when the list is not empty, after another thread executed notify() or notifyAll() somewhere else in the code.
read more why use while surrounding wait()
BUT with the following code:
synchronized(monitor) {
if(!list.isEmpty())
doSomething(...)
}
When a thread comes in to the synchronized block, there are 3 possible scenarios:
The list is empty: doSomething() will not be executed.
The list is NOT empty: doSomething() may be executed properly, or...
If there was a context switch right after the if and before doSomething, and the other thread got all list's items out, after another context-switch out thread will execute doSomethig() on an empty list.
So, just to sum everything up, if you use wait/notify, you guarantee more efficient code! thread will not work when they don't need to.
Related
I have a small question that makes me a little confused.
This is my code:
public synchronized void P() {
while(!_state) {
this.wait();
}
_state = false;
}
This method is responsible for taking semaphore.
Why it is not possible to build binary semaphore with if statement instead of while loop?
The oracle docs says:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is
done with the object.
So exactly only one thread should be inside the P() method -> so only one thread should be blocked on wait() method. Rest of threads should be blocked on P() method level. But when I am replacing while() for if() it does not work properly
Why it is not possible to build binary semaphore with if statement instead of while loop?
For a deep answer, you should work through Oracle's Guarded Blocks tutorial.
The shorter answer is, there's a couple of reasons why _state could be false when the wait() call returns:
Multiple consumers: It generally is safer to wake sleepers with notifyAll() instead of notify(), and if you write a program in which two or more threads could call the P() function, you probably only want one of them to be allowed to proceed when some other thread calls the V() function. So, if they all "wake up", you'll want just one to set _state=false; and you'll want the others to go back to sleep.
The same object is getting notifyAll() calls for more than one reason. It's not good practice, but it happens, especially in projects where many developers contribute to the code. In that case, you don't wan the P() call to return if the object was notified for the wrong reason. You want it to go back and continue waiting.
The documentation for o.wait() says that it is allowed to return even when object o has not been notified at all. This is known as "spurious wakeup." It happens rarely, and only in some operating systems, but they allow it because it enables a more efficient implementation of wait() and notify().
synchronized method is equivalent to synchronized(this) block.
Only 1 thread is allowed to enter synchronized block. By entering it, thread aquires lock. When you wait inside sync block, you release the lock (object monitor) and park current thread. At this moment, another thread is allowed to enter that block. Execution will continue when other thread will invoke notify or notifyAll on the same object that wait was invoked. Notified thread will "exit wait state" when given sync block's lock will be released.
To sum up - wait does not work like you expect, it does not block execution, only puts waiting thread to sleep, allowing other threads to aquire sync lock.
So you cannot do what you want to achieve, because wait works differently then you expect. What you want to use here, is ReentrantLock. https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html
I have a ReentrantLock in my code and want to use it to clear an array once per second; I dont want other threads to change the array while it is being cleared, but if I am not currently clearing the array other threads shall not have to wait, like this:
public void addToArray(Object a) {
lock.waitforunlock(); //not a real method just to clarify my intentions
array.add(a);
}
To better clarify my intentions I will explain the process: the netty eventloop will call my network handler, that network handler will then call the addToArray method from before, once per second my main thread that will never be a Netty thread will clear the array, in this time every netty thread shall have to wait until this is finished! Note: the addToArray method is threadproof and I dont want to sync it because then the hole point of a event loop is useless.
There is no API method that does exactly what you are asking.
The most efficient way to do it is like this:
try {
lock.lock();
} finally {
lock.unlock();
}
In other words, grab the lock momentarily then release it.
But here's the problem.
In general, the instant you release the lock, some other thread might immediately grab it. So your array.add() call may happen simultaneously with some other thread doing things to array. Even if your use-case means that another thread grabbing the lock is highly unlikely, it can still happen; e.g. if your server is under severe load and the current thread gets preempted immediately after releasing the lock.
Presumably you are performing memory writes in array.add(). Unless they are performed with appropriate synchronization, those updates may not be visible to other threads. (You say "addToArray method is threadproof", but without a clear, detailed explanation of what you mean by that, I would be uncomfortable with saying this code is thread safe.)
If what you are trying to do here is to array.add() after something else has happened, then testing the lock / waiting for it to be released doesn't tell you if the event actually happened. All it tells you is that it wasn't happening at the instant that the test succeeded.
In short, I doubt that waiting for a lock to be released before doing an update is actually a correct solution ... no matter how you implement the waiting.
Another way to look at this.
If array.add() is completely threadsafe, and will work correctly irrespective of some other thread holding the lock, why do you need to test the lock? Just call the method.
If you are actually trying to have the array.add() call happen after some event that coincides with the lock being released, use a cyclic barrier or similar.
Note: I read and tried to understand your explanation, but I got lost with what you are saying. Due to "language issues" I think.
As I understand it, you have two or more separate threads mutating a list: the main thread occasionally clearing the list, and the netty thread adding to the list. You want to make sure they don't both attempt to modify the list at the same time.
The simplest solution to this is to use a thread safe list, and make sure the main thread uses the List.clear() method to clear the list. That way, the clear() call will be atomic - once started it will finish before any other accesses to the list - so you won't have to worry about adding to the list "in the middle of" the clear() call.
In a comment to another answer, you mention that you are using a CopyOnWriteArrayList, which is thread safe. Thus, you can just call add() the code that adds to the list without worrying about synchronization; the add() call will automatically wait if the list is being cleared, and proceed otherwise. You can also remove the use of the ReentrantLock from your main thread unless there are other reasons, besides protecting this list, to use the lock.
Whenever I write Thread.sleep(500); in my code, it always tells me this sometimes causes problems to use Thread.sleep();. Is there another way to delay time before certain things. If so, can you give me the code and explanation. Thank you
Firstly, you don't show us any code and you don't mention what "it" is. (As in "it always tells me ...".) This makes a specific answer impossible.
It most likely that the problem referred to is that sleep makes your code either wasteful or unresponsive. A common "hack" used to make a thread wait for some condition is to repeatedly call sleep and then test the condition. The problem is that if the condition becomes true while you are sleeping, the thread will still be held up until the sleep interval expires. If you make the sleep interval smaller, then you "burn" more CPU cycles with wakeup / test / sleep iterations.
If you are trying to implement a "wait for some condition to become true", then the efficient way to do it is to either use wait() and notify() (or notifyAll()), or an appropriate higher level synchronization class.
The classic Java pattern is like this:
// waiting for the condition
synchronized (obj) {
while (!condition) {
obj.wait();
}
}
...
// updating the condition ...
synchronized (obj) {
// do something that makes condition true
obj.wait();
}
Note that the use of synchronized is essential if you use wait/notify.
Condition interface can be useful to let other threads notify you about specific events and ask the current thread to get "parked" till then. Condition interface also has a methods called waitUntil(Date deadline) - which causes current thread to wait until the deadline elapses.
Are you waiting for some other thread to perform some activity and wait till then? Use any blocking data structure like BlockingQueue or other advanced synchronizers like CountdownLatch.
If just waiting for some thread to complete its execution use join().
As mentioned bay MadProgrammer and alfasin, its important to know what you are trying to achieve and what is the problem in sleep() you are talking about.
If you want something to happen in the near future, using sleep repeatedly is a bad thing. For once it does not guarantee to be "on time", and for second it can be interrupted at any time, causing your program to malfunction.
If you have one part of your code that needs to be executed repeatedly, using a Timer can solve that perfectly. If you have multiple and different parts of code that need to be executed with given delays, you should use a ScheduledExecutorService. You can either use the ScheduledThreadPoolExecutor directly or - more conveniently - use the ExecutorService.
You can easily circumvent threading issues by just using a single thread. However threading isn't that difficult in Java if you use the right tools.
I have two blocks of code, one waits for the other to notify it.
synchronized(this) {
wait();
}
and
while(condition) {
//do stuff
synchronized(this) {
notify();
}
}
Weirdly enough that didn't wait for the notify while this did:
synchronized(objectLock) {
objectLock.wait();
}
and
while(condition) {
//do stuff
synchronized(objectLock) {
objectLock.notify();
}
}
I'm very curious about the difference of both sets, and why the first one worked while the other didn't. Note that the two blocks reside in two different threads on two different methods (if that helps).
I hope someone could explain why this is so. I edited my question so it would be more detailed.
It didn't work because you synchronized on this which in two different threads pointed to two different Thread objects.
Synchronization with wait() and notify() would only work properly when you synchronize on the same object for locking like the objectLock that you used later on.
EDIT:
If the two thread instances belonged to the same MyThread class then to achieve the effect that you thought you're code was having, you would have to acquire a lock on their class object itself:
synchronized(MyThread.class)
You can use any object you like. However, it is generally clearer to other programmers to see an explicit lock object.
My wild guess as to why this didn't work for you is you had a different this in scope. (ie, in an anonymous function/callback). You can be explicit about which this to use by appending the class name, eg, WonderClass.this - again a reason why this is not as clear. (edit: actually WhateverClass.this won't help you if this really is a different instance)
Also do read this: http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html - I generally find it easier to put all the thread-unsafe code into small synchronized methods (which do an implict lock on this)
When you say the two blocks reside in two different threads that makes me think they're not locking on the same object because this is not the same thing. When you name an explicit lock you're using the same thing to lock on.
By the way you should call wait in a loop, like this:
synchronized(someLock) {
while (!someCondition) {
wait();
}
// now the thread has the lock and it can do things
// knowing for sure that someCondition is true
}
Without this you will be vulnerable to spurious wakeups (not all notifications come from your application code) and the order in which wait and notify are called becomes problematic (if you have two threads and one notifies before the other waits then that notification never gets seen).
I'd advise using the Monitor pattern (http://en.wikipedia.org/wiki/Monitor_(synchronization)) anyway, that could save you from errors later on, especially as your use case gets more complex:
class Monitor
{
/** Initialised to `false` by default in Java. */
boolean condition;
synchronized void waitForSomething()
{
while(!condition)
{
wait();
}
}
synchronized void signal()
{
condition = true;
notify();
}
}
That way everything is nicely encapsulated and protected (I don't usually use private modifiers in examples, but you might want to enforce additional "privacy" in your code, specifically making the condition private.)
As you can observe, in my condition loop there is wait() call, as opposed to your example where you have notify() in the loop instead. In most use cases doing what you did with notify is a mistake, although I can't speak for your particular case as you didn't provide us with enough details. I am willing to bet yours is the typical one though, for which the Monitor pattern applies beautifully.
The usage scenario is along the following: thread that wants to wait for something calls waitForSomething and another thread may cause it to continue by invoking signal method which will set the condition flag.
Theoretical question. If I have two SwingWorkers and an outputObject with method
public void synchronized outputToPane(String output)
If each SwingWorker has a loop in it as shown:
//SwingWorker1
while(true) {
outputObject.outputToPane("garbage");
}
//SwingWorker2
Integer i=0;
while(true) {
outputObject.outputToPane(i.toString());
i++;
}
How would those interact? does the outputToPane method receive an argument from one thread and block the other one until it finishes with the first, or does it build a queue of tasks that will execute in the order received, or some other option?
The reason I ask:
I have two threads that will be doing some heavy number crunching, one with a non-pausable data stream and the other from a file. I would like them both to output to a central messaging area when they hit certain milestones; however, I CANNOT risk the data stream getting blocked while it waits for the other thread to finish with the output. I will risk losing data then.
synchronized only guarantees mutual exclusion. Is not fair, which in practice means that your workers might alternate quite nicely, or the first one might get precedence and block the second one completely until finished, or anything between.
See Reentrantlock docs for more about fairness. Maybe you could consider using it instead of synchronized. Probably even better alternative would be using a Queue.
I would advise you to have two output object in your messaging area. Because if one thread starts to modify the output answer then the other one will have to wait for it to finish. Even if you can optimize it to make it fast enough, the actual display of info would make your threads slow each others down over time.
Although you might try to synchronize them, the result might not always be 100% safe