Need a java synchronization aid similar to ReentrantReadWriteLock. But I want that acquired read lock can be released in another thread.
See code example with my comments:
public class Pool {
// specific synchronization aid, which I want to find
ReadWriteLock lock;
public void acquire() {
// increment count of readers, initial value for reader count = 0,
// possible reader count is unlimited
lock.readerCountIncrement();
}
public void release() {
// decrement count of readers
lock.readerCountDecrement();
}
public void write() {
// if method called, forbid (block on) readerCountIncrement()
// and wait until readers count become = 0
lock.writeLockAcquire();
try {
// some actions
} finally {
// release and allow readerCountIncrement()
lock.writeLockRelease();
}
}
}
Related
// this is just an example to better understand. I would like to understand if it is necessary or not to lock I don't know if this example is suitable for what I want to understand .............................................................................................................................................................................................
class Counter{
int counter;
public ReentrantLock lock=new ReentrantLock();
//if the variable is visible to more Threads all readings and writes must be Thread-safe?
public void incr() {
lock.lock();
try {
counter++;
} finally {
lock.unlock();
}
}
public void decr() {
lock.lock();
try {
counter--;
} finally {
lock.unlock();
}
}
//must have Lock
public int getincr() {
return counter;
}
}
//these are the Thread
public class Worker extends Thread {
private Counter c;
public Worker (Counter c) {
this.c=c;
}
enter code here
public void run() {
System.out.println(Thread.currentThread().getName());
for(int i=1;i<=10;i++) {
c.incr(); System.out.println(c.getincr());//this is the method
c.decr(); System.out.println(c.getincr());
}
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//Main
public class Test {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
Counter c=new Counter();
Worker[] threads = new Worker[100];
for(int i=0;i<100;i++) {
threads[i]=new Worker(c);
threads[i].start();
//threads[i].join();
}
}
}
Try adding the following two lines to the end of your main method and then adding and removing the locking code.
Thread.sleep(10000);
System.out.println("Final counter value: " + c.counter)
What you will see if you run the main method a few times is the following:
When you don't have the explicit locking around the incrementing and decrementing of the counter, the end value of the counter might be incorrect.
When you have the explicit locking around the counter variable, the final counter value will always be correct (zero) at the end of the test.
An explanation of the above behaviour is that with locking, the value of the counter that is being accessed is always correct. Since both increment and decrement use the same explicit lock object before operating on the counter variable, the JVM guarantees that you will have the latest value of the variable.
Regarding the getincr() in the Counter class, since the value that it accesses and returns might also at the same time be incremented or decremented by another thread (than the one that is doing the reading), you need to acquire a lock in order to ensure that you are reading the latest value of the counter. To quote the authoritative book Concurrency in Practice (section 2.4. Guarding State with Locks):
It is a common mistake to assume that synchronization needs to be used only when writing to shared variables; this is simply not true. For each mutable state variable that may be accessed by more than one thread, all accesses to that variable must be performed with the same lock held. In this case, we say that the variable is guarded by that lock.
Another way of implementing your locking could have been to use a ReentrantReadWriteLock, in which case the Counter class methods incr() and decr() would acquire write locks and the getincr() method would acquire a read lock.
Additionally, since only one operation is performed in each of the Counter methods incr(), decr() and getincr(), you could substitute locking with the use of an AtomicInteger for your counter variable (instead of using an int), which would also provide thread-safe access.
Reentrant Lock ( https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html ) has a feature to state the strength of locking by a particular Thread which is based on the value of 'hold count'. It is initilized when a Thread aquires the lock and each time when it re-aquires the lock the value is incremented. The value is decremented each time the thread invokes the unlock method on the lock.
Single thread at a time can be the owner of the Reentrant Lock hence simple boolen flag makes mcuh sense rather than an integers count. A thread already being the owner of the lock can only re-aquire it so count seams not of much. (any) use.
What is the usefulness of hold count ? What are the use cases of it ? One such use case can be to check of the current thread is holding the lock (hold count value > 0). But there are different APIs like isHeldByCurrentThread().
The API documentation for that method explains it :
The hold count information is typically only used for testing and debugging purposes.
So it's basically a method that can help you track down instances where your code fails to call unlock(). This is especially true for cases where you have reentrant usage of the lock.
Suppose you have a method includes a locked block, you can call it from different place. This method should do different thing according to the lock count it holds. Then you can take use of getHoldCount.
import java.util.concurrent.locks.ReentrantLock;
public class Example {
ReentrantLock lock = new ReentrantLock();
void method1() {
lock.lock();
try {
if (lock.getHoldCount() == 1) {
System.out.println("call method1 directly");
} else if (lock.getHoldCount() == 2) {
System.out.println("call method1 by invoking it inside method2");
}
} finally {
lock.unlock();
}
}
void method2() {
lock.lock();
try {
method1();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
Example example = new Example();
example.method1(); // call method1 directly
example.method2(); // call method1 by invoking it inside method2
}
}
In the docs for CountDownLatch I see something like:
public void run() {
try {
startSignal.await();
doWork();
doneSignal.countDown();
} catch (InterruptedException ex) {} // return;
}
Here startSignal and doneSignal are CountDownLatch objects.
The docs don't mention anything about the class being thread-safe or not.
As it is designed to be used by multiple threads it would be fair to assume that it is thread-safe to most meanings of thread-safe.
There is even a happens-before commitment (from your link):
Memory consistency effects: Until the count reaches zero, actions in a thread prior to calling countDown() happen-before actions following a successful return from a corresponding await() in another thread.
With reference to your specific question What if two threads call countDown at the same time? Wouldn't it just do the count down action only once effectively? No, two countDowns will be actioned every time.
Yes the class or rather the methods you call on a CountDownLatch objects arr thread-safe.
In order to make these operations such as countDown() await() thread-safe, they have not used synchronize block or functions. Rather they have used Compare and Swap strategy.
Below is the source codes which proves the same
sync.releaseShared(1);
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
The above code is a part of the total implementation, you can check source codes for other methods like await() as well.
I was trying to implement something similar to Java's bounded BlockingQueue interface using Java synchronization "primitives" (synchronized, wait(), notify()) when I stumbled upon some behavior I don't understand.
I create a queue capable of storing 1 element, create two threads that wait to fetch a value from the queue, start them, then try to put two values into the queue in a synchronized block in the main thread. Most of the time it works, but sometimes the two threads waiting for a value start seemingly waking up each other and not letting the main thread enter the synchronized block.
Here's my (simplified) code:
import java.util.LinkedList;
import java.util.Queue;
public class LivelockDemo {
private static final int MANY_RUNS = 10000;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < MANY_RUNS; i++) { // to increase the probability
final MyBoundedBlockingQueue ctr = new MyBoundedBlockingQueue(1);
Thread t1 = createObserver(ctr, i + ":1");
Thread t2 = createObserver(ctr, i + ":2");
t1.start();
t2.start();
System.out.println(i + ":0 ready to enter synchronized block");
synchronized (ctr) {
System.out.println(i + ":0 entered synchronized block");
ctr.addWhenHasSpace("hello");
ctr.addWhenHasSpace("world");
}
t1.join();
t2.join();
System.out.println();
}
}
public static class MyBoundedBlockingQueue {
private Queue<Object> lst = new LinkedList<Object>();;
private int limit;
private MyBoundedBlockingQueue(int limit) {
this.limit = limit;
}
public synchronized void addWhenHasSpace(Object obj) throws InterruptedException {
boolean printed = false;
while (lst.size() >= limit) {
printed = __heartbeat(':', printed);
notify();
wait();
}
lst.offer(obj);
notify();
}
// waits until something has been set and then returns it
public synchronized Object getWhenNotEmpty() throws InterruptedException {
boolean printed = false;
while (lst.isEmpty()) {
printed = __heartbeat('.', printed); // show progress
notify();
wait();
}
Object result = lst.poll();
notify();
return result;
}
// just to show progress of waiting threads in a reasonable manner
private static boolean __heartbeat(char c, boolean printed) {
long now = System.currentTimeMillis();
if (now % 1000 == 0) {
System.out.print(c);
printed = true;
} else if (printed) {
System.out.println();
printed = false;
}
return printed;
}
}
private static Thread createObserver(final MyBoundedBlockingQueue ctr,
final String name) {
return new Thread(new Runnable() {
#Override
public void run() {
try {
System.out.println(name + ": saw " + ctr.getWhenNotEmpty());
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
}, name);
}
}
Here's what I see when it "blocks":
(skipped a lot)
85:0 ready to enter synchronized block
85:0 entered synchronized block
85:2: saw hello
85:1: saw world
86:0 ready to enter synchronized block
86:0 entered synchronized block
86:2: saw hello
86:1: saw world
87:0 ready to enter synchronized block
............................................
..........................................................................
..................................................................................
(goes "forever")
However, if I change the notify() calls inside the while(...) loops of addWhenHasSpace and getWhenNotEmpty methods to notifyAll(), it "always" passes.
My question is this: why does the behavior vary between notify() and notifyAll() methods in this case, and also why is the behavior of notify() the way it is?
I would expect both methods to behave in the same way in this case (two threads WAITING, one BLOCKED), because:
it seems to me that in this case notifyAll() would only wake up the other thread, same as notify();
it looks like the choice of the method which wakes up a thread affects how the thread that is woken up (and becomes RUNNABLE I guess) and the main thread (that has been BLOCKED) later compete for the lock — not something I would expect from the javadoc as well as searching the internet on the topic.
Or maybe I'm doing something wrong altogether?
Without looking too deeply into your code, I can see that you are using a single condition variable to implement a queue with one producer and more than one consumer. That's a recipe for trouble: If there's only one condition variable, then when a consumer calls notify(), there's no way of knowing whether it will wake the producer or wake the other consumer.
There are two ways out of that trap: The simplest is to always use notifyAll().
The other way is to stop using synchronized, wait(), and notify(), and instead use the facilities in java.util.concurrent.locks.
A single ReentrantLock object can give you two (or more) condition variables. Use one exclusively for the producer to notify the consumers, and use the other exclusively for the consumers to notify the producer.
Note: The names change when you switch to using ReentrantLocks: o.wait() becomes c.await(), and o.notify() becomes c.signal().
There appears to be some kind of fairness/barging going on using intrinsic locking - probably due to some optimization. I am guessing, that the native code checks to see if the current thread has notified the monitor it is about to wait on and allows it to win.
Replace the synchronized with ReentrantLock and it should work as you expect it. The different here is how the ReentrantLock handles waiters of a lock it has notified on.
Update:
Interesting find here. What you are seeing is a race between the main thread entering
synchronized (ctr) {
System.out.println(i + ":0 entered synchronized block");
ctr.addWhenHasSpace("hello");
ctr.addWhenHasSpace("world");
}
while the other two thread enter their respective synchronized regions. If the main thread does not get into its sync region before at least one of the two, you will experience this live-lock output you are describing.
What appears to be happening is that if both the two consumer threads hit the sync block first they will ping-pong with each other for notify and wait. It may be the case the JVM gives threads that are waiting priority to the monitor while threads are blocked.
I am on my way learning Java multithread programming. I have a following logic:
Suppose I have a class A
class A {
ConcurrentMap<K, V> map;
public void someMethod1 () {
// operation 1 on map
// operation 2 on map
}
public void someMethod2 () {
// operation 3 on map
// operation 4 on map
}
}
Now I don't need synchronization of the operations in "someMethod1" or "someMethod2". This means if there are two threads calling "someMethod1" at the same time, I don't need to serialize these operations (because the ConcurrentMap will do the job).
But I hope "someMethod1" and "someMethod2" are mutex of each other, which means when some thread is executing "someMethod1", another thread should wait to enter "someMethod2" (but another thread should be allowed to enter "someMethod1").
So, in short, is there a way that I can make "someMethod1" and "someMethod2" not mutex of themselves but mutex of each other?
I hope I stated my question clear enough...
Thanks!
I tried a couple attempts with higher-level constructs, but nothing quite came to mind. I think this may be an occasion to drop down to the low level APIs:
EDIT: I actually think you're trying to set up a problem which is inherently tricky (see second to last paragraph) and probably not needed (see last paragraph). But that said, here's how it could be done, and I'll leave the color commentary for the end of this answer.
private int someMethod1Invocations = 0;
private int someMethod2Invocations = 0;
public void someMethod1() {
synchronized(this) {
// Wait for there to be no someMethod2 invocations -- but
// don't wait on any someMethod1 invocations.
// Once all someMethod2s are done, increment someMethod1Invocations
// to signify that we're running, and proceed
while (someMethod2Invocations > 0)
wait();
someMethod1Invocations++;
}
// your code here
synchronized (this) {
// We're done with this method, so decrement someMethod1Invocations
// and wake up any threads that were waiting for that to hit 0.
someMethod1Invocations--;
notifyAll();
}
}
public void someMethod2() {
// comments are all ditto the above
synchronized(this) {
while (someMethod1Invocations > 0)
wait();
someMethod2Invocations++;
}
// your code here
synchronized(this) {
someMethod2Invocations--;
notifyAll();
}
}
One glaring problem with the above is that it can lead to thread starvation. For instance, someMethod1() is running (and blocking someMethod2()s), and just as it's about to finish, another thread comes along and invokes someMethod1(). That proceeds just fine, and just as it finishes another thread starts someMethod1(), and so on. In this scenario, someMethod2() will never get a chance to run. That's actually not directly a bug in the above code; it's a problem with your very design needs, one which a good solution should actively work to solve. I think a fair AbstractQueuedSynchronizer could do the trick, though that is an exercise left to the reader. :)
Finally, I can't resist but to interject an opinion: given that ConcurrentHashMap operations are pretty darn quick, you could be better off just putting a single mutex around both methods and just being done with it. So yes, threads will have to queue up to invoke someMethod1(), but each thread will finish its turn (and thus let other threads proceed) extremely quickly. It shouldn't be a problem.
I think this should work
class A {
Lock lock = new Lock();
private static class Lock {
int m1;
int m2;
}
public void someMethod1() throws InterruptedException {
synchronized (lock) {
while (lock.m2 > 0) {
lock.wait();
}
lock.m1++;
}
// someMethod1 and someMethod2 cannot be here simultaneously
synchronized (lock) {
lock.m1--;
lock.notifyAll();
}
}
public void someMethod2() throws InterruptedException {
synchronized (lock) {
while (lock.m1 > 0) {
lock.wait();
}
lock.m2++;
}
// someMethod1 and someMethod2 cannot be here simultaneously
synchronized (lock) {
lock.m2--;
lock.notifyAll();
}
}
}
This probably can't work (see comments) - leaving it for information.
One way would be to use Semaphores:
one semaphore sem1, with one permit, linked to method1
one semaphore sem2, with one permit, linked to method2
when entering method1, try to acquire sem2's permit, and if available release it immediately.
See this post for an implementation example.
Note: in your code, even if ConcurrentMap is thread safe, operation 1 and operation 2 (for example) are not atomic - so it is possible in your scenario to have the following interleaving:
Thread 1 runs operation 1
Thread 2 runs operation 1
Thread 2 runs operation 2
Thread 1 runs operation 2
First of all : Your map is thread safe as its ConcurrentMap. This means that operations on this map like add,contains etc are thread safe.
Secondaly
This doesn't guarantee that even your methods (somemethod1 and somemethod2) are also thread safe. So your methods are not mutually exclusive and two threads at same time can access them.
Now you want these to be mutex of each other : One approach could be put all operations (operaton 1,..operation 4) in a single method and based on condition call each.
I think you cannot do this without a custom synchronizer. I've whipped up this, I called it TrafficLight since it allows threads with a particular state to pass while halting others, until it changes state:
public class TrafficLight<T> {
private final int maxSequence;
private final ReentrantLock lock = new ReentrantLock(true);
private final Condition allClear = lock.newCondition();
private int registered;
private int leftInSequence;
private T openState;
public TrafficLight(int maxSequence) {
this.maxSequence = maxSequence;
}
public void acquire(T state) throws InterruptedException {
lock.lock();
try {
while ((this.openState != null && !this.openState.equals(state)) || leftInSequence == maxSequence) {
allClear.await();
}
if (this.openState == null) {
this.openState = state;
}
registered++;
leftInSequence++;
} finally {
lock.unlock();
}
}
public void release() {
lock.lock();
try {
registered--;
if (registered == 0) {
openState = null;
leftInSequence = 0;
allClear.signalAll();
}
} finally {
lock.unlock();
}
}
}
acquire() will block if another state is active, until it becomes inactive.
The maxSequence is there to help prevent thread starvation, allowing only a maximum number of threads to pass in sequence (then they'll have to queue like the others). You could make a variant that uses a time window instead.
For your problem someMethod1() and someMethod2() would call acquire() with a different state each at the start, and release() at the end.