I am writing a utility class to implement the behavior of a stopwatch. One important feature of this class is that it is designed to be thread-safe. I use a private final field called lock to synchronize on. Two of the methods in the class are called reset and start, which reset the stopwatch and start it, respectively. They are implemented as:
public void reset() {
synchronized (lock) {
beginTime = 0;
lapIndex = 0;
}
}
public void start() {
synchronized (lock) {
if (beginTime == 0) {
beginTime = System.nanoTime();
laps[lapIndex++] = beginTime;
}
}
}
Recently, I had the idea of adding an additional convenience method called restart, which would reset and the start the stopwatch. I want this to behave like an atomic operation, so my idea was to implement it as:
public void restart() {
synchronized(lock) {
reset();
start();
}
}
However, the reset and start methods already synchronize on lock, so invoking restart would synchronize on the same object two times. Could any problems arise from that? Is the behavior of synchronizing on the same object multiple times well-defined? Is it necessary? I have ran the code as it seems to work fine, but I fear I could be missing some subtleties as is common with multithreading.
There's no problem with synchronizing twice. The thread already owns the monitor so the extra synchronization doesn't really do much. This will be necessary, otherwise your restart() method might be interrupted by another thread between calls to reset() and start().
A way of avoiding the double synchronization is to have restart(), reset(), and start() synchronize and then delegate to non-synchronized internal methods.
public void reset() {
synchronized (lock) {
_reset();
}
}
public void start() {
synchronized (lock) {
_start();
}
}
public void restart() {
synchronized(lock) {
_reset();
_start();
}
}
private void _reset() {
beginTime = 0;
lapIndex = 0;
}
private void _start() {
if (beginTime == 0) {
beginTime = System.nanoTime();
laps[lapIndex++] = beginTime;
}
}
From section 14.19 on synchronized statements of the Java language specification:
The locks acquired by synchronized statements are the same as the locks that are acquired implicitly by synchronized methods (§8.4.3.6). A single thread may acquire a lock more than once.
Also from the JLS:
A thread t may lock a particular monitor multiple times; each unlock reverses the effect of one lock operation.
Therefore, this shouldn't be a problem.
Related
I'm trying to create thread safe queue in java. I've come across this example:
class ProducerConsumer<T> {
private static final int BUFFER_MAX_SIZE = 42;
private List<T> buffer = new LinkedList<>();
synchronized void produce(T value) throws InterruptedException {
while (buffer.size() == BUFFER_MAX_SIZE) {
wait();
}
buffer.add(value);
notify();
}
synchronized T consume() throws InterruptedException {
while (buffer.size() == 0) {
wait();
}
T result = buffer.remove(0);
notify();
return result;
}
}
I'm new to java. In my understanding those two 'synchronized' keywords would prevent contention inside each method, but not when both methods are called simultaneously. E.g. thread P calls produce, locks method, thread C calls consume, locks other method, then one tries to extract element from list, another tries to insert element, thread exception arises.
My question: Is this example broken?
Or maybe I'm missing something and it's ok.
JLS, §17.1 is quite explicit about the mechanism:
...
A synchronized method (§8.4.3.6) automatically performs a lock action when it is invoked; its body is not executed until the lock action has successfully completed. If the method is an instance method, it locks the monitor associated with the instance for which it was invoked (that is, the object that will be known as this during execution of the body of the method). If the method is static, it locks the monitor associated with the Class object that represents the class in which the method is defined. If execution of the method's body is ever completed, either normally or abruptly, an unlock action is automatically performed on that same monitor.
...
Thus, it is guaranteed that at one point in time on one object at most one thread is executing either produce(...) or consume(). It is not possible that, at one point in time, one thread executes produce(...) on an object while another thread executes consume() on the same object.
The call to wait() in consume() releases the intrinsic lock and blocks execution. The call to notify() in produce(...) notifies one wait()ing thread (if any), so it can fight for the lock as soon as the lock is released by the current owner. Notice that a call to notify() does not release the intrinsic lock. It just wakes up a wait()ing thread. This can be made observable with the following code snippet:
class Ideone {
private static final Object lock = new Object();
public static void main(String[] args) {
printWithThreadNamePrefix("Start");
Thread waiter = new Thread(Ideone::waiter);
waiter.start();
// Give waiter some time to a) start and b) acquire the intrinsic lock
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
final Thread notifier = new Thread(Ideone::notifier);
notifier.start();
while (true) {
try {
waiter.join();
break;
} catch (InterruptedException e) {
}
}
printWithThreadNamePrefix("End");
}
private static void waiter() {
synchronized (lock) {
printWithThreadNamePrefix("Waiting...");
while (true) {
try {
lock.wait();
break;
} catch (InterruptedException e) {
}
}
printWithThreadNamePrefix("... done waiting");
}
}
private static void printWithThreadNamePrefix(String msg) {
System.out.println(String.format(
"%s: %s",
Thread.currentThread().getName(),
msg));
}
private static void notifier() {
synchronized (lock) {
printWithThreadNamePrefix("notifying");
lock.notify();
while (true) {
}
}
}
}
Ideone demo
The program will never terminate. Although thread two calls notify(), it then enters an endless loop, never actually releasing the intrinsic lock. Thus, one never has a chance to acquire the intrinsic lock, and the program "hangs" (it is neither a deadlock, nor a livelock, it simply cannot proceed).
The things I recommend to change are:
declare private List<T> buffer additionally as final
call notifyAll() instead of notify() in order to wake all waiting threads (they will still execute sequentially, for details see this question by Sergey Mikhanov and its answers)
I was looking for a way to make one thread wait/sleep until another thread signalled that something was ready. The waiting thread should wake up, process the data that was made available, then go back to sleep until the other thread signalled again.
The simplest method I could find was Object.wait() and Object.notify(), which behaved like a semaphore initialised to value 0. However, without the synchronized statements around notify/wait, Java always threw IllegalMonitorStateException when the thread was not the monitor owner. So I simply put them around the code like shown below.
THREAD 1: running infinite loop
public class Main {
private Handler handler; // only one instance (singleton pattern)
public void listen() {
while (true) {
try {
synchronized (handler) {
handler.wait();
int value = handler.getSize();
// do something
}
} catch (InterruptedException e) {
// ...
}
}
}
}
THREAD 2: Some other class calls removeItem
public class Handler {
// SINGLETON PATTERN - ONLY ONE INSTANCE
private ArrayList<Integer> sharedList;
private Handler() {
sharedList = new ArrayList<>();
}
public void addItem(Integer i) {
synchronized (sharedList) {
// add to list
}
}
public void removeItem(int i) {
synchronized (sharedList) {
// remove item
// notify that something is removed
synchronized (this) {
this.notify(); // this == handler
}
}
}
public int getSize() {
synchronized (sharedList) {
return sharedList.size();
}
}
}
It seems to work perfectly fine but not sure if there is a hidden bug.
My question is: Is this safe? Does wait release the instance lock for handler/this so notify can acquire the lock?
Synchronized blocks are safe. The statement synchronized(obj) acquires the lock of the argument obj, so you can call wait and notify on it. They both require that the current thread holds the lock on the object.
You have to be careful about the double-locking you have in removeItem where you lock two objects. If you ever need this, you have to make sure that you always lock them in the same order, otherwise, you may create a deadlock.
Say I have a class with 2 instance variables and the following methods (simplified for this question):
private final Object lock = new Object();
private boolean running;
public MyClass() {
synchronized(lock) {
running = false;
}
}
public void methodA() {
synchronized(lock) {
running = true;
}
}
public void methodB() {
synchronized(lock) {
if (!running) {
return;
}
}
}
I was looking at this code, and after reading about AtomicBoolean, I thought that one might fit here, especially after looking at the MyClass constructor and methodA. I wasn't too sure about methodB though.
Assuming these methods could get called by multiple threads, would the following be thread-safe?:
private AtomicBoolean running;
public MyClass() {
running = new AtomicBoolean(false);
}
public void methodA() {
running.set(true);
}
public void methodB() {
if (!running.get()) {
return;
}
}
Will running.get() be guaranteed to see an update via running.set(true) or running.set(false) from another thread?
In your example, a simple volatile boolean would be enough, since you only seem to be doing atomic operations. AtomicBoolean is useful if you need the methods such as compareAndSet.
So in answer to your question, yes, when using a volatile boolean or an AtomicBoolean, other threads will see the updates to the variable.
Generally speaking these code blocks are not equal for methodB, because reading volatile variable does not create synchronization order.
Imagine you have some other field int x = 42 in your class, that is updated in methodB:
public void methodB() {
if (!running.get()) {
return;
}
if (x < 50) x++; // just example
}
Then you have several threads that call methodB:
when using synchronized keyword, updates are safe and visible to all threads.
when using AtomicBoolean/volatile visibility is broken
If there is no such case with variable updates and the task is just to guarantee visibility between methodA - methodB sequence, then it's OK - AtomicBoolean is enough for that.
Yes. From the Javadoc of AtomicBoolean:
A {#code boolean} value that may be updated atomically.
This means that any update to AtomicBoolean is indivisible. So, I would consider such use of AtomicBoolean to be thread safe.
You should still consider making the declaration of AtomicBoolean final:
private final AtomicBoolean running;
I'm working on a multithreaded Java project where I would like to have objects that prevent their methods from being called from any thread for some period of time. Ideally, those method calls would not be thrown out, but simply queued up until the cooldown from the previous method has completed. Here's a simple example of a class with that kind of functionality:
public class A {
private synchronized void cooldown(long ms) {
long finishTime = ms + System.currentTimeMillis();
while (System.currentTimeMillis() < finishTime);
}
public synchronized void foo() {
// foo's code
cooldown(1000);
}
public synchronized void bar() {
// bar's code
cooldown(2000);
}
}
This works, but I'm expecting to have quite a few of the above objects and I feel like the loop inside of cooldown() is wasteful. I'd love to use a construct like Thread.sleep(), but in this case, that would have the undesirable effects of forcing the calling thread to sleep and not preventing any other thread from making method calls on A. Any suggestions?
EDIT:
To clarify, given the following implementation:
public synchronized void foo() {
System.out.println("foo");
cooldown(1000);
}
public synchronized void bar() {
System.out.println("bar");
cooldown(2000);
}
public static void main(String[] args) {
final A a = new A();
new Thread(new Runnable() {
public void run() {
a.foo();
}
}).start();
System.out.println("foobar");
new Thread(new Runnable() {
public void run() {
a.bar();
}
}).start();
}
I would like foo and foobar to print instantly (order doesn't matter), followed by bar a second later. If cooldown() just called Thread.currentThread().sleep(ms) instead of the current implementation, then foo would print instantly, followed by foobar and bar a second later.
I'd love to use a construct like Thread.sleep(), but in this case, that would have the undesirable effects of forcing the calling thread to sleep and not preventing any other thread from making method calls on A. Any suggestions?
I don't see the difference between calling Thread.sleep() versus your spin loop aside from the fact that the spin loop wastes CPU. If you are inside cooldown(...) then that instance of A is synchronized.
If you mean that you have other methods that are synchronized and you don't want the thread that is cooling down to be holding the lock then you can use this.wait(...) which will release the lock during the sleep. Of course is someone is calling notify(...) this won't work.
private synchronized void cooldown(long ms) {
try {
long waitUntilMillis = System.currentTimeMillis() + ms;
long waitTimeMillis = ms;
do {
this.wait(waitTimeMillis);
// we need this dance/loop because of spurious wakeups, thanks #loki
waitTimeMillis = waitUntilMillis - System.currentTimeMillis();
} while (waitTimeMillis > 0);
} catch (InterruptedException e) {
Thread.currentThread.interrupt();
}
}
The right thing to do is to not have synchronized methods and only synchronize when you specifically need to. Then you can cooldown easily without holding a lock.
private void cooldown(long ms) {
try {
this.sleep(ms);
} catch (InterruptedException e) {
Thread.currentThread.interrupt();
}
}
public void foo() {
synchronized (this) {
// foo's code
}
cooldown(1000);
}
You have following options:
Thread.sleep() should work fine if called inside synchronized method. All other threads would be prevented and your thread will hold lock and wait.
Use timed wait/notify in a synchronized block. That should also do the job.
EDIT:
See the below code
public class A {
final volatile Object lck = new Object();
volatile boolean waitStatus = true;
private void cooldown(long ms) {
synchronized(lck){
long startTime = System.currentTimeMillis();
//Do thread need to wait
if(waitStatus){
while(System.currentTimeMillis()-startTime < ms)
lck.wait(gapTime);
//Wait over no other thread will wait
waitStatus = false;
}
}
}
public void foo() {
// foo's code
cooldown(1000);
}
public void bar() {
// bar's code
cooldown(2000);
}
}
You are very close already ... minor change ...
private synchronized void cooldown(long ms) throws InterruptedException {
Thead.sleep(ms);
}
Alternatively, you could handle the InterruptedException in the cooldown method itself.
Also, note that your code could actually execute foo, bar, and foobar in any order. The cooldown will slow down the foo or the bar (depending on which gets executed first).
I'd love to use a construct like Thread.sleep(), but in this case,
that would have the undesirable effects of forcing the calling thread
to sleep and not preventing any other thread from making method calls
on A.
Your approach does what you want. Other threads ARE prevented from making method calls on A (if you have synchronized the methods - which you have).
I have a queue with some blocking mechanism in "Add" and "Get" methods, where first thread adds data and second thread gets data.
public synchronized MyObj getData() {
synchronized (myLock) {
synchronized (this) {
if (isEmpty()) {
wait(0);
}
}
return getData();
}
}
public synchronized void addData(MyObj data) {
if (!isFull()) {
putData(data);
synchronized (this) {
notify();
}
}
}
In the code above, if first thread tries to get data and queue is empty i put in wait via wait(0) until other thread add data to queue an release from waiting via notify().
Now I want to add another "lock" when queue is full and some one tries to add more data to it:
public synchronized MyObj getData() {
synchronized (myLock) {
synchronized (this) {
if (isEmpty()) {
wait(0);
}
}
synchronized (this) {
notify();
}
return getData();
}
}
public synchronized void addData(MyObj data) {
synchronized (myLock) {
synchronized (this) {
if (isFull()) {
wait(0);
}
}
}
synchronized (this) {
notify();
}
PutData(data);
}
The result is not what I expect , I guess that i get a dead lock cause process is stuck.
UPDATE
This is how I get data:
queueSize--;
startPointer = (startPointer + 1) % mqueueSize;
data = (String) queue[startPointer];
this is how i add data
queueSize++;
endPointer = (endPointer + 1) % mqueueSize;
queue[endPointer] = data;
public synchronized boolean isEmpty() {
return queueSize== 0;
}
public synchronized boolean isFull() {
return queueSize== mqueueSize;
}
Why do you have three synchronized statements? The wait(0) only releases the lock on this, so just keep that one and dump the synchronized from the method and the synchronized(myLock).
Whenever you call wait on some object (in this case you are calling on this), the lock on that object is automatically released to allow the other thread to proceed. But you are never calling wait on myLock (and nor should you, because you are calling on this already). That part is redundant and causes the deadlock.
Consider this scenario: the thread that is supposed to add takes the lock on myLock but finds the queue full, so it waits. This wait does not release the lock on myLock. The other thread wants to take data but cannot enter the synchronized block because the first thread did not release the lock on myLock.
Conclusion: remove the synchronized(myLock) blocks.
Why you don't take a look in java.util.BlockingQueue. Probably it will be useful in your situation.
Particularly take a look at java.util.LinkedBlockingQueue, where if you specify the queue's capacity in the constructor, then the queue will block.
Remove the synchronized keyword from your method signatures, as that implies you hold the this monitor for the whole method call -- the synchronized(this) blocks are simply redundant.
EDIT:
...Then call wait and notify on myLock rather than this. And forget completely about synchronizing on this. This is because while waiting (on this in your current code), you're not releasing the myLock lock, so the other thread is not able to get to notify().
Replace if with while. It won't hurt to double check, if the collection really become not empty/not full.
You don't really need two locks. Single lock will work almost as well and should be much simpler.
public synchronized T get()
{
while(isEmpty())
wait(0);
notifyAll();
return super.get();
}
public synchronized put(T t)
{
while(isFull())
wait(0);
super.put(t);
notifyAll();
}
All threads will wake up when something changes. But if they can't do their work, they will wait for next notify.
As already mentioned, your code has too many synchronized annotations. Also, the condition to wait on is checked in an if conditional, but it should ideally be checked in a while loop to avoid spurious wakeups. Here is the outline of the code that fixes these.
// _isEmpty and _getData are private unsynchronized methods
public MyData get() throws InterruptedException {
// wait and notify should be called from a block
// synchronized on the same lock object (here myLock)
synchronized (myLock) {
// the condition should be tested in a while loop
// to avoid issues with spurious wakeups
while (_isEmpty()) {
// releases the lock and wait for a notify to be called
myLock.wait();
}
// when control reaches here, we know for sure that
// the queue is not empty
MyData data = _getData();
// try to wake up all waiting threads - maybe some thread
// is waiting for the queue not to be full
myLock.notifyAll();
}
}
// _isFull and _putData are private unsynchronized methods
public void put(MyData obj) throws InterruptedException {
synchronized (myLock) {
while (_isFull()) {
myLock.wait();
}
_putData(obj);
myLock.notifyAll();
}
}