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.
Related
I have been experimenting with Kotlin synchronization and I do not understand from the docs on how the locking mechanism works on thread synchronization over common resources and thus attempted to write this piece of code which further complicates my understanding.
fun main() {
val myList = mutableListOf(1)
thread {
myList.forEach {
while (true) {
println("T1 : $it")
}
}
}
thread {
synchronized(myList) {
while (true) {
myList[0] = 9999
println("**********\n**********\n**********\n")
}
}
}
}
myList is the common resource in question.
The first thread is a simple read operation that I intend to keep the resource utilized in read mode. The second is another thread which requests a lock in order to modify the common resource.
Though the first thread does not contain any synchronization, I would expect it to internally handle this so that a while a function like map or forEach is in progress over a resource, another thread should not be able to lock it otherwise the elements being iterated over may change while the map/forEach is in progress (even though that operation may be paused for a bit while another thread has a lock over it).
The output I see instead shows that both the threads are executing in parallel. Both of them are printing the first element in the list and the stars respectively. But in the second thread, even though the stars are being printed, myList[0] is never set to 9999 because the first thread continues to print 1.
Threading and synchronisation are JVM features, not specific to Kotlin. If you can follow Java, there are many resources out there which can explain them fully. But the short answer is: they're quite low-level, and tricky to get right, so please exercise due caution. And if a higher-level construction (work queues/executors, map/reduce, actors...) or immutable objects can do what you need, life will be easier if you use that instead!
But here're the basics. First, in the JVM, every object has a lock, which can be used to control access to something. (That something is usually the object the lock belongs to, but need not be...) The lock can be taken by the code in a particular thread; while it's holding that lock, any other thread which tries to take the lock will block until the first thread releases it.
And that's pretty much all there is! The synchronised keyword (actually a function) is used to claim a lock; either that belonging to a given object or (if none's given) 'this' object.
Note that holding a lock prevents other threads holding the lock; it doesn't prevent anything else. So I'm afraid your expectation is wrong. That's why you're seeing the threads happily running simultaneously.
Ideally, every class would be written with some consideration for how it interacts with multithreading; it could document itself as 'immutable' (no mutable state to worry about), 'thread-safe' (safe to call from multiple threads simultaneously), 'conditionally thread-safe' (safe to call from multiple threads if certain patterns are adhered to), 'thread-compatible' (taking no special precautions but callers can do their own synchronisation to make it safe), or 'thread-hostile' (impossible to use from multiple threads). But in practice, most don't.
In fact, most turn out to be thread-compatible; and that applies to much of the Java and Kotlin collection classes. So you can do your own synchronisation (as per your synchronized block); but you have to take care to synchronise every possible access to the list -- otherwise, a race condition could leave your list in an inconsistent state.
(And that can mean more than just a dodgy value somewhere. I had a server app with a thread that got stuck in a busy-loop -- chewing up 100% of a CPU but never continuing with the rest of the code -- because I had one thread update a HashMap while another thread was reading it, and I'd missed the synchronisation on one of those. Most embarrassing.)
So, as I said, if you can use a higher-level construction instead, your life will be easier!
Second thread is not changing the value of the first list element, as == means compare, not assign. You need to use = tio change the value e.g. myList[0] = 9999. However in your code it's not guaranteed that the change from the second thread will become visible in the first thread as thread one is not synchronising on myList.
If you are targeting JVM you should read about JVM memory model e.g. what is #Volatile. You current approach does not guarantee that first thread will ever see changes from the second one. You can simplify your code to below broken example:
var counter = 1
fun main() {
thread {
while (counter++ < 1000) {
println("T1: $counter")
}
}
thread {
while (counter++ < 1000) {
println("T2: $counter")
}
}
}
Which can print strange results like:
T2: 999
T1: 983
T2: 1000
This can be fixed in few ways e.g. by using synchronisations.
Someone at work just asked for the reasoning behind having to wrap a wait inside a synchronized.
Honestly I can't see the reasoning. I understand what the javadocs say--that the thread needs to be the owner of the object's monitor, but why? What problems does it prevent? (And if it's actually necessary, why can't the wait method get the monitor itself?)
I'm looking for a fairly in-depth why or maybe a reference to an article. I couldn't find one in a quick google.
Oh, also, how does thread.sleep compare?
edit: Great set of answers--I really wish I could select more than one because they all helped me understand what was going on.
Lots of good answers here already. But just want to mention here that the other MUST DO when using wait() is to do it in a loop dependent on the condition you are waiting for in case you are seeing spurious wakeups, which in my experience do happen.
To wait for some other thread to change a condition to true and notify:
synchronized(o) {
while(! checkCondition()) {
o.wait();
}
}
Of course, these days, I'd recommend just using the new Condition object as it is clearer and has more features (like allowing multiple conditions per lock, being able to check wait queue length, more flexible schedule/interrupt, etc).
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock();
try {
while (! checkCondition()) {
condition.await();
}
} finally {
lock.unlock();
}
}
If the object does not own the object monitor when it calls Object.wait(), it will not be able to access the object to setup a notify listener until the the monitor is released. Instead, it will be treated as a thread attempting to access a method on a synchronized object.
Or to put it another way, there is no difference between:
public void doStuffOnThisObject()
and the following method:
public void wait()
Both methods will be blocked until the object monitor is released. This is a feature in Java to prevent the state of an object from being updated by more than one thread. It simply has unintended consequences on the wait() method.
Presumably, the wait() method is not synchronized because that could create situations where the Thread has multiple locks on the object. (See Java Language Specifications/Locking for more info on this.) Multiple locks are a problem because the wait() method will only undo one lock. If the method were synchronized, it would guarantee that only the method's lock would be undone while still leaving a potential outer lock undone. This would create a deadlock condition in the code.
To answer your question on Thread.sleep(), Thread.sleep() does not guarantee that whatever condition you are waiting on has been met. Using Object.wait() and Object.notify() allows a programmer to manually implement blocking. The threads will unblock once a notify is sent that a condition has been met. e.g. A read from disk has finished and data can be processed by the thread. Thread.sleep() would require the programmer to poll if the condition has been met, then fall back to sleep if it has not.
It needs to own the monitor, since the purpose of the wait() is to release the monitor and let other threads obtain the monitor to do processing of their own. The purpose of these methods (wait/notify) is to coordinate access to synchronized code blocks between two threads that require each other to perform some functionality. It is not simply a matter of making sure access to a data structure is threadsafe, but to coordinate events between multiple threads.
A classic example would be a producer/consumer case where one thread pushes data to a queue, and another thread consumes the data. The consuming thread would always require the monitor to access the queue, but would release the monitor once the queue is empty. The producer thread would then only get access to write to the thread when the consumer is no longer processing. It would notify the consumer thread once it has pushed more data into the queue, so it can regain the monitor and access the queue again.
Wait gives up the monitor, so you must have it to give it up. Notify must have the monitor as well.
The main reason why you want to do this is to ensure that you have the monitor when you come back from wait() -- typically, you are using the wait/notify protocol to protect some shared resource and you want it to be safe to touch it when wait returns. The same with notify -- usually you are changing something and then calling notify() -- you want to have the monitor, make changes, and call notify().
If you made a function like this:
public void synchWait() {
syncronized { wait(); }
}
You would not have the monitor when wait returned -- you could get it, but you might not get it next.
Here's my understanding on why the restriction is actually a requirement. I'm basing this on a C++ monitor implementation I made a while back by combining a mutex and a condition variable.
In a mutex+condition_variable=monitor system, the wait call sets the condition variable into a wait state and releases the mutex. The condition variable is shared state, so it needs to be locked to avoid race conditions between threads that want to wait and threads that want to notify. Instead of introducing yet another mutex to lock its state, the existing mutex is used. In Java, the mutex is correctly locked when the about-to-wait thread owns the monitor.
Mostly wait is done if there is a condition say a queue is empty.
If(queue is empty)
queue.wait();
Let us assume the queue is empty.
In case if the current thread pre-empts after checking the queue, then if another
thread adds few elements to queue, the current thread will not know and will go for wait
state. Thats wrong.
So we should have something like
Synchornized(queue)
{
if(queue is empty)
queue.wait();
}
Now let us consider what if they made wait itself as synchronized. As already mentioned in one of the comments, it releases only one lock. That means if wait() was synchronized in the above code only one lock would have been released. Implies that current thread will go for wait with the lock for the queue.
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.
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
I'm doing a code review for a change in a Java product I don't own. I'm not a Java expert, but I strongly suspect that this is pointless and indicates a fundamental misunderstanding of how synchronization works.
synchronized (this) {
this.notify();
}
But I could be wrong, since Java is not my primary playground. Perhaps there is a reason this is done. If you can enlighten me as to what the developer was thinking, I would appreciate it.
It certainly is not pointless, you can have another thread that has a reference to the object containing the above code doing
synchronized(foo) {
foo.wait();
}
in order to be woken up when something happens. Though, in many cases it's considered good practice to synchronize on an internal/private lock object instead of this.
However, only doing a .notify() within the synchronization block could be quite wrong - you usually have some work to do and notify when it's done, which in normal cases also needs to be done atomically in regards to other threads. We'd have to see more code to determine whether it really is wrong.
If that is all that is in the synchonized block then it is an antipattern, the point of synchronizing is to do something within the block, setting some condition, then call notify or notifyAll to wake up one or more waiting threads.
When you use wait and notify you have to use a condition variable, see this Oracle tutorial:
Note: Always invoke wait inside a loop that tests for the condition being waited for. Don't assume that the interrupt was for the particular condition you were waiting for, or that the condition is still true.
You shouldn't assume you received a notification just because a thread exited from a call to Object#wait, for multiple reasons:
When calling the version of wait that takes a timeout value there's no way to know whether wait ended due to receiving a notification or due to timing out.
You have to allow for the possibility that a Thread can wake up from waiting without having received a notification (the "spurious wakeup").
The waiting thread that receives a notification still has to reacquire the lock it gave up when it started waiting, there is no atomic linking of these two events; in the interval between being notified and reacquiring the lock another thread can act and possibly change the state of the system so that the notification is now invalid.
You can have a case where the notifying thread acts before any thread is waiting so that the notification has no effect. Assuming one thread will enter a wait before the other thread will notify is dangerous, if you're wrong the waiting thread will hang indefinitely.
So a notification by itself is not good enough, you end up guessing about whether a notification happened when the wait/notify API doesn't give you enough information to know what's going on. Even if other work the notifying thread is doing doesn't require synchronization, updating the condition variable does; there should at least be an update of the shared condition variable in the synchronized block.
This is perfectly fine. According to the Java 6 Object#notify() api documentation:
This method should only be called by a thread that is the owner of this object's monitor.
This is generally not a anti-pattern, if you still want to use intrinsic locks. Some may regard this as an anti pattern, as the new explicit locks from java.util.concurrent are more fine grained.
But your code is still valid. For instance, such code can be found in a blocking queue, when an blocking operation has succeeded and another waiting thread should be notified. Note however that concurrency issues are highly dependent on the usage and the surrounding code, so your simple snippet is not that meaningful.
The Java API documentation for Object.notify() states that the method "should only be called by a thread that is the owner of this object's monitor". So the use could be legitimate depending upon the surrounding context.