I am creating a mutli threaded application, and I have a question regarding the use of synchronized methods.
Lets say I have the following component which would be accessed by multiple threads.
Component.java
public class Component {
private boolean active;
//Constructor
public Component(){
active = false;
}
synchronized public void initiate(){
//do something
active = true;
}
synchronized public void closedown(){
//do something
active = false;
}
public void doSomething(){
//do something
}
public boolean isActive(){
return active;
}
}
If I have two threads accessing the the same Component object and the first thread gets halted in the Component.closedown() before it has set active = false, and the second thread picks up and calls Component.isActive(), will the second thread block until the first thread has finished the closedown, or will it get the returned value of true?
If it is the latter, how can I make this thread safe?
Yes, that is the essence of mutual-exclusion locks (mutexes). If a thread gets descheduled by the OS while holding a mutex, all other threads requiring the mutex to proceed will be stalled.
The above is actually the reason why, even if we take care to make all our critical sections very short and fast to execute, mutexes will still cause occasional latency spikes, and the spikes will be huge in proportion to regular latency. For example, your simple getter will execute in a couple of nanoseconds when uncontended, but may take 10µs or more if the thread holding the mutex is descheduled at an inconvenient time.
NOTE: The code in your question lacks the synchronized designation on isActive, but I assume your question is about what would happen if it was synchronized—because the code has a data race without it. Specifically:
will the second thread block until the first thread has finished the closedown, or will it get the returned value of true?
Without synchronized it will do neither: it won't block, but it won't be guaranteed to ever return the true value. You are only guaranteed to observe the initial value (that's what the data race is about).
If you are looking for a practical advice to improve your code, then don't synchronize isActive method, but make the active flag volatile. This is standard practice for your use case.
You need to have use a lock to protect the critical sections. As some methods read from the value and some write to the value, you can try using a ReadWriteLock.
public class Component {
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private boolean active;
//Constructor
public Component(){
active = false;
}
public void initiate(){
// non-critical section
rwl.writeLock().lock();
try {
// critical section
active = true;
} finally {
rwl.writeLock().unlock();
}
}
public void closedown(){
// non-critical section
rwl.writeLock().lock();
try {
// critical section
active = false;
} finally {
rwl.writeLock().unlock();
}
}
public void doSomething(){
// do something
}
public boolean isActive(){
rwl.readLock().lock();
boolean status = active;
rwl.readLock().unlock();
return status;
}
}
Related
I'm studying for an exam from a Book given by my professor and there is this code working with Threads and Synchronization: We want to be notified everytime the state changes (without missing a state change).
public class C {
private int state = 0; // the state
private boolean modified = false; // to show if the state was changed since actualization
public synchronized void printNewState() {
while (true) {
if (!modified) {
wait();
}
System.out.println(state);
modified = false;
notify();
}
}
public synchronized void setValue(int v) {
if (modified) {
wait();
}
state = v;
notify();
modified = true;
System.out.println("value set");
}
}
And then it's writen:
However, it is not guaranteed that notify() in the method SetValue(int) wakes up the printNewState Thread! In Java we solve this problem
with the help of notifyAll() and take a little busy waiting:
public synchronized void printNewState() {
while (true) {
while (!modified) {
wait();
}
System.out.println(state);
modified = false;
**notify();** \\(?)
}
}
public synchronized void setValue(int v) {
while (modified) {
wait();
}
state = v;
notifyAll();
modified = true;
System.out.println("value set");
}
I don't understand why the notify wasn't also changed to notifyAll()? It might not be guaranteed that this notify goes to a Thread of setValue(int) ???
Thank you
The notify() method wakes up a single waiting thread, whereas the notifyAll() method wakes up all the waiting threads. The problem is that with notify(), the thread that is woken up is effectively random.
If some other thread is accidentally or maliciously wait()ing on the same object, it could receive the notification instead of the thread you expect to wake up.
Take a look at this answer for some more information. The comments on that answer are also quite interesting.
EDIT
In the code sample you posted, the first notify() within printNewState() can handle only one update at a time, so it doesn't make sense to notify all waiting threads to post their updates. The code assumes, however, that only threads invoking setValue(int) are waiting.
Since public synchronized void setValue(int) is essentially the same as having synchronized(this) as the first line of the method, that isn't actually guaranteed. Any code that has a reference to an instance of C class can wait on it and screw up the code.
The synchronization and wait/notify actions should happen on an object lock/monitor. private final Object monitor = new Object(), synchronized(this.monitor), this.monitor.wait(), this.monitor.notifyAll(), etc.
I would also like to note that modified = true needs to be placed before notifyAll() in setValue(int), otherwise other waiting update threads will proceed without printNewState() noticing the update.
Also, private boolean modified should really be private volatile boolean modified, and the same for private int state, though an AtomicInteger may be a better option.
The question may seem pretty obvious, but it's not clear to me anyway.
I have the following class:
public class MyClass{
private Object lock = new Object();
private boolean flag;
public void method(){
//Start synchronization block
if(!flag){
flag = true;
//end synchronization block
//do some bulk operation, should be synchronized
}
//some other staff
}
}
The thing is I cannot put the piece of code I need to be synchronized, because it will not be correct. How to do such synchronization? Maybe there's something from java.util.concurrent that I could make use of.
You can also do it without explicit synchronization, using an AtomicBoolean:
public class MyClass{
private AtomicBoolean flag = new AtomicBoolean(false);
public void method(){
if(flag.compareAndSet(false, true)) {
//do some bulk operation, should be synchronized
}
//some other staff
}
}
This will only enter the block if nothing has entered it before, and is thread safe.
Of course, there may be other things in the block which also require synchronization. However, this works for the stated problem.
Your code looks like a perfect use case for AtomicBoolean, which has a method compareAndSet which atomically checks the value of the boolean and sets it if the check returns the expected value:
private AtomicBoolean flag = new AtomicBoolean();
public void method() {
if (flag.compareAndSet(false, true)) {
// ...
}
// other stuff
}
You can grab the object's monitor using synchronized(this){/*ToDo - synchronised code here*/}
Alternatively, you can synchronise on one of the object's fields if acquiring the object's monitor will cause concurrency issues.
This way you can use synchronized block:
synchronized(this)
{
// synchronized block
}
Don't forget about java.util.concurrent.locks.Lock, which is more powerful (and therefore, more dangerous) than Java's built-in locking. It lets you do things like this:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
final Lock myLock = new ReentrantLock();
myLock.lock();
if (...) {
...
myLock.unlock();
...
} else {
myLock.unlock();
...
}
The following code will work, but I slightly resent having to write the isRunning() method:
class Test {
private boolean running;
public void startX() {
synchronized(this) {
running = true
}
while (isRunning()) {
//do something
}
}
public synchronized void stopX() {
running = false;
}
private synchronized boolean isRunning() {
return running;
}
}
Can I synchronize reads of the running variable in the while (running){} in some other way, or do I have to write the isRunning() method? The same question applies to other control variables as well, eg
for (;running;) {}
or
if (running) {}
In all of these cases it seems as though you're forced into writing a pointless method to get the synchronization correct. Am I missing something?
if you are only resetting the value of running once to designate to stop, you might be able to use the volatile keyword.
However, if you need to start and stop many times, this won't work. This is because volatile fields "may miss an update"
Here's a link to explanation of when volatile works in cases like this link
here's the code sample from that link incase it goes dead:
public class StoppableTask extends Thread {
private volatile boolean pleaseStop;
public void run() {
while (!pleaseStop) {
// do some stuff...
}
}
public void tellMeToStop() {
pleaseStop = true;
}
}
If you need to start and stop many times, then you need to either use one of the Java 5 concurrent lock objects or explicit synchronization
You could make the running field volatile. Making the field volatile puts the JVM on notice that it should make changes to that field visible to other threads.
The "miss an update" caveat is for cases where you want to read a value and update based on that value, which doesn't seem applicable here.
Multiple threads can write to this field, if all they're doing is setting a boolean flag then this won't be a problem.
Alternatively, if you are trying to cancel a thread, there's already an equivalent flag provided on Thread for this (and the visibility issue is taken care of). You can call interrupt on a thread, the code in the Runnable can query Thread.currentThread().isInterrupted() in order to tell whether it's been interrupted. This is preferable over using your own flag because the interruption will cause the thread to wake up if it is waiting or sleeping. With your own flag you have to wait until control reaches a place where the flag can be tested.
just to add up to other people's answer that suggested volatile .
Alternatively you could create a class for the checks.
I have made the variable to be static, so all threads will be pointing to same object.
class Runner{
boolean static running=true;
public static synchronized boolean getRunning(){
return running;
}
public static synchronized boolean setRunning(boolean r){
running=r;
}
}
NOTE:
if you don't require the global variable, then remove the static
I have a long-running Runnable. It performs a large number of iterations inside a while-loop in its run() function. I need functionality to pause and resume the runnable, which I implemented using a volatile Boolean pauseFlag that can be set by another thread.
Once the Runnable has detected that pauseFlag is true, it calls pauseFlag.wait() to pause its execution. Resuming is done through setting pauseFlag to false and then calling pauseFlag.notifyAll().
So the pauseFlag both acts as a flag and a mutex. This combined functionality does not work, however. The Runnable keeps blocking on pauseFlag.wait() indefinitely.
If I create a separate mutex, say, Object mutex = new Object(); and use mutex.notifyAll() / mutex.wait(), while still using pauseFlag as a boolean flag, the Runnable does behave as intended.
The non-working code is shown below:
public class PausableRunnable implements Runnable
{
private boolean done;
private volatile Boolean pauseFlag = false;
/** Pause execution. This is an asynchronous (non-blocking) call. */
public void pause() // <-- called by another thread
{
pauseFlag = true;
}
/** Resume execution */
public void resume() // <-- called by another thread
{
pauseFlag = false;
synchronized (pauseFlag)
{
pauseFlag.notifyAll();
}
}
#Override
public void run()
{
try
{
while (!done && !Thread.currentThread().isInterrupted())
{
while (pauseFlag)
{
synchronized (pauseFlag)
{
// Pause flag was set. Suspend until we are notified that we can continue
pauseFlag.wait();
}
}
// execute our main behaviour. set done = true when done iterating.
// ....
}
} catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
}
}
So, while I have found a solution by using a separate object, I'd like to understand the issue. Why doesn't the above implementation work?
I made this very same mistake once.
wait/notify works on an object, not a reference
When you change the object referred to by
private volatile Boolean pauseFlag
the wait is still referring to the original object. (As pointed out in the comments, there will usually be only two Boolean objects, TRUE and FALSE, making this even harder to debug, because you might get the correct one by chance)
So it's best to use a final reference that never changes its underlying object when using wait/notify.
I'm just testing some concurrent programming in Java.
Basically I have a class (Light) which is a kind of finite state machine, and changing its state regarding the commands.
That's what I'm trying to: The light is in ON state, I send a command to the thread of this class for changing the state in OFF.
But I got a problem during the execution.
First, let me present the class:
enum State {ON, OFF};
public class Light implements Runnable {
private boolean cmdOn;
private boolean cmdOff;
State state;
public Light() {
cmdOn = false;
cmdOff = false;
state = State.ON;
}
#Override
public void run() {
while(true) {
switch(state) {
case ON:
if(cmdOff) {
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
state = State.OFF;
}
break;
case OFF:
if(cmdOn) {
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
state = State.ON;
}
break;
}
}
}
public void setCmdOn(boolean cmdOn) {
this.cmdOn = cmdOn;
}
public void setCmdOff(boolean cmdOff) {
this.cmdOff = cmdOff;
}
public State getState() {
return state;
}
}
And my main class:
public class Main {
public static void main(String args[]) throws InterruptedException {
Light light = new Light();
Thread t = new Thread(light);
t.start();
printState(light, 500, 1);
light.setCmdOff(true);
printState(light, 500, 4);
}
public static void printState(Light l, int time, int number) throws InterruptedException {
for(int i= 0; i < number; i++) {
System.out.println(l.getState());
Thread.currentThread().sleep(time);
}
}
The output shows me that I'm stuck in the ON state while I should be in OFF state.
In a second run, after putting an instruction (System.out.println or whatever...) above the if statement which verify that cmdOff is true, it's magically works.
I don't understand why the cmdOff variable is not pass to true during the first run !?
And why in the second run it works?
I miss something, probably a synchronizing block. But I don't find the explanation to deal with this.
Thanks.
Best regards,
You should read about synchronization. Without synchronization you risk getting visibility errors where one thread can't see changes another thread made to a variable shared between the threads.
Tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html
You can use a synchronized block that uses an object both threads know about to do locking. If both threads always synchronize on that known object when reading or updating your shared data, then visibility and atomicity will never be an issue.
Read here to fully understand "synchronized": http://tutorials.jenkov.com/java-concurrency/synchronized.html
You should also be able to just declare the shared variable as volatile. This means all writes and reads on it create a happens-before relationship with other threads, which is what you want. Read the tutorial above to fully understand the issues and terminology.
Read here to fully understand "volatile": http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html.
Try using volatile on cmdOn and cmdOff:
private volatile boolean cmdOn;
private volatile boolean cmdOff;
Volatile variable explanation in Java docs
Without it (or synchronization) changes may not be visible.
Without any synchronization, there are no guarantees that the running thread will ever see the values written to cmdOff and cmdOn by the other thread. Also, lack of synchronization on state means any changes by the running thread may not be seen by the other thread. Try making cmdOn, cmdOff and state volatile .