Fine-tuning Java synchronized block behavior - java

I have two synchronized blocks of code. I need the two blocks of code not to be able to be running simultaneously in two or more different threads, but I would like to allow two or more different threads to run one of the blocks of code simultaneously. How can this be done in Java? To exemplify:
class HelloWorld {
method1() {
synchronized (?) { //block 'A'
//I want to allow 2+ threads to run this code block simultaneously
}
}
method2() {
synchronized (?) { //block 'B'
//this should block while another thread is running
//the synchronized block 'A'
}
}
I don't want both synchronized blocks to lock on the same object/class, because that would disallow the first block from being run by multiple threads simultaneously. However, it is the only way I know of to prevent block A and B from running simultaneously by 2 or more threads. There must be a way to achieve this.

I suggest to look into the ReadWriteLock respectively the implementing class ReentrantReadWriteLock. That thing is espeically designed to allow multiple "reader" threads; but only one "writer" thread.
If i read your question correctly, that is exactly what you are asking for. On the other hand, it might also be wise to step back and eloborate what the real problem is that you are trying to solve here.
Especially given the fact that the aforementioned lock works nicely with Java8, but saw problems in earlier version of Java.

Maybe something like:
private CommonStateSynchronizer synchronizer = new CommonStateSynchronizer();
public void method1() throws InterruptedException
{
synchronizer.run("method1", () -> {
// do method1
});
}
public void method2() throws InterruptedException
{
synchronizer.run("method2", () -> {
// do method2
});
}
public static class CommonStateSynchronizer
{
private final ReentrantReadWriteLock rw;
private final ReentrantReadWriteLock.ReadLock r; // hold read lock while executing in current state
private final ReentrantReadWriteLock.WriteLock w; // hold write lock while checking or changing state
private final Condition stateChanged;
private volatile String currentState; // do not modify unless holding write lock
public CommonStateSynchronizer()
{
rw = new ReentrantReadWriteLock(true);
r = rw.readLock();
w = rw.writeLock();
stateChanged = w.newCondition();
}
public void run(String state, Runnable runnable) throws InterruptedException {
w.lock();
while (!state.equals(currentState))
{
if (currentState == null)
{
currentState = state;
stateChanged.notifyAll();
break;
}
stateChanged.await();
}
assert state.equals(currentState);
// downgrade to concurrent read lock
r.lock();
w.unlock();
try
{
runnable.run();
}
finally
{
r.unlock();
w.lock();
if (rw.getReadLockCount() == 0)
{
currentState = null;
stateChanged.notifyAll();
}
w.unlock();
}
}
}

Related

java, synchronized in two separate methods?

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)

Java optimized read/write a shared resource/memory location without Atomic API e.g. AtomicInteger

There is a shared resource and we need to perform read/write operations on it as per below:
When a write on resource is going on then no read should be allowed.
When a read is going on then no write should be allowed but multiple read threads should be able to read.
I have written code like mentioned below but the problem with this code is all reads will be blocked when a single read thread has acquired the lock. Further i am thinking to use a boolean flag e.g. canReadContinue. Now the first time when read acquires a lock i will flip this flag to true and if it is true then other threads should not try to acquire the lock.
class SharedResource {
Lock writeLock
public Object read() {
writeLock.acquire()
doRead()
}
public void write(Object toBeWritten) {
writeLock.acquire()
doWrite(toBeWritten)
writeLock.release()
}
}
Expected is multiple threads should be able to read when no write is going on.
UPDATED 1 :
public class SharedResource {
private Object writeLock = new Object();
private volatile boolean canReadContinue;
private volatile int readCount;
public void write(Object newState) throws InterruptedException {
synchronized (writeLock) {
// To make sure no read is going on
while (readCount > 0) {
wait();
}
System.out.println("Write thread has the lock.");
doWrite(newState);
}
}
public Object read() {
if(canReadContinue) {
incrementCount();
} else {
synchronized (writeLock) {
System.out.println("Read thread has the lock.");
canReadContinue = true;
incrementCount();
}
}
Object result = doRead();
decrementCount();
if(readCount == 0) {
// TODO - release lock and notify
}
return result;
}
private synchronized void incrementCount() {
readCount++;
}
private synchronized void decrementCount() {
readCount--;
}
private void doWrite(Object newState) {
// do stuff
}
private Object doRead() {
return "";
}
}
Now i need a mechanism to release the lock at line "// TODO - release lock and notify", any pointers how to resolve this issue ?
Hints:
You need a mutex; e.g. a primitive object lock.
You need a counter of the number of readers currently holding a logical read lock.
You need a flag to say if a writer is holding a logical write lock.
You hold the mutex if and only you are acquiring or releasing a logical lock. Once you have acquired it, you release the mutex.
You will need to use wait and notify.
Effectively you need to1 implement a simplified version ReadWriteLock.
1 - ... for the purposes of your homework assignment. In a real world program, you should simply use the existing ReadWriteLock class.
Answering on your updated code here is some skeleton for you to complete:
public class SharedResource {
private final Object signal = new Object();
private boolean writeLocked;
private int readerCount;
public void write(final Object newState) throws InterruptedException {
this.acquireWriteLock();
try {
// Now we know that no read and no other write is going on.
System.out.println("Write thread has the lock.");
this.doWrite(newState);
} finally {
// make sure we release the lock in any case.
this.realeaseWriteLock();
}
}
private void acquireWriteLock() throws InterruptedException {
synchronized (this.signal) {
// Wait until no more readers *and* no writer holds the lock.
// To do: Insert the condition we need to wait for:
while (/* condition here! */ ) {
// To do: Wait for the lock-holding thread(s) to signal that they released their lock(s).
}
this.writeLocked = true; // Let others know that the write lock has been taken.
}
}
private void realeaseWriteLock() {
synchronized (this.signal) {
this.writeLocked = false;
// To do: Notify any and all other waiting threads that we released the lock!
}
}
public Object read() {
// To be done...
}
private void acquireReadLock() throws InterruptedException {
synchronized (this.signal) {
// Wait until no *writer* holds the lock.
// To do: Insert condition we need to wait for:
while (/* condition here! */ ) {
// To do: Wait for the lock-holding thread(s) to signal that they released their lock(s).
}
// Now we know that no writer holds the lock. Acquire (another) read lock:
this.readerCount++;
}
}
private void releaseReadLock() throws InterruptedException {
synchronized (this.signal) {
this.readerCount--;
// To do: Notify any threads waiting (i.e. writer threads).
// (In fact only *required* if there are *no* more readers now because that's the only condition any thread will wait on.)
}
}
private void doWrite(final Object newState) {
// do stuff
}
private Object doRead() {
return "";
}
}
The main point to understand may be that every attempt to take a lock may have to wait, and that every release of a lock should notify any (potential) waiting threads.
Further i am thinking to use a boolean flag e.g. canReadContinue
You're on the right track. But remember that any number of threads could concurrently perform their read accesses and that the write access can only be done if no other thread is currently reading or writing.
So you need to keep track of how many readers are currently holding the lock, and every reader must make sure to release the lock when it's done. Only if & when 0 readers (and 0 writers) hold the lock, a writer may proceed; and only if & when 0 writers hold the lock, any reader may proceed.

Java - Synchronized but allow one method to be accessed by different threads

In the example below:
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
inc1 and inc2 can be accessed at the same time, but neither can be accessed by multiple threads at the same time.
How would it be possible to allow only inc1 or inc2 to be accessed whilst the other is like regular syncing however allowing the one that is being accessed to be done so by as many threads as possible.
I think a useful analogy is traffic passing through an intersection, where you can have multiple cars sharing one road, as long as they're driving in parallel. The challenge is finding a coordination strategy for intersecting traffic.
The solution proposed by #Greg works if traffic is intermittent and we can wait for one stream to stop before allowing the intersecting stream to proceed. But I suspect that's not very realistic. If there's steady traffic on one road, the rest of the cars will wait forever, a.k.a. thread starvation.
An alternative strategy is to allow cars to cross on a first come, first served basis, like at a stop sign. We can implement that using a dedicated semaphore for each "road", or segment, where each user takes a permit, after first making sure none of the other segments have permits in use:
public class StopSign {
private final Semaphore[] locks;
private volatile int current = 0;
public StopSign(int segments) {
// create and populate lock array, leaving
// all segments drained besides the first
locks = new Semaphore[segments];
Arrays.setAll(locks, i -> new Semaphore(i == 0 ? Integer.MAX_VALUE : 0, true));
}
public void enter(int segment) {
// synchronization is necessary to guard `current`,
// with the added benefit of holding up new threads
// in the active segment while we're gathering permits
synchronized (locks) {
if (segment == current) {
// if our segment is active, acquire a permit
locks[segment].acquireUninterruptibly();
} else {
// otherwise, gather all permits from the active segment
// as they become available and then reclaim our own permits
locks[current].acquireUninterruptibly(Integer.MAX_VALUE);
current = segment;
locks[segment].release(Integer.MAX_VALUE - 1);
}
}
}
public void exit(int segment) {
if (segment != current) {
// we don't own the lock!
throw new IllegalMonitorStateException();
}
locks[segment].release();
}
}
To use the class, we simply call enter(i) and exit(i), where i identifies the road/segment/method we want to use. Here's a demo using 3 segments:
public static void main(String args[]) {
int segments = 3;
StopSign lock = new StopSign(segments);
IntStream.range(0, segments).parallel().forEach(i -> {
for (int j = 0; j < 10; j++) {
lock.enter(i);
System.out.print(i);
lock.exit(i);
sleepUninterruptibly(20, TimeUnit.MILLISECONDS);
}
});
}
A test run on my machine produces this alternating pattern:
120201210012012210102120021021
This strategy could make sense if traffic is relatively light, but in heavy traffic the overhead of coordinating each crossing can significantly restrict throughput. For busy intersections, you'll usually want a traffic light, or a third party that can transfer control at a reasonable frequency. Here's an implementation of a such a concept, using a background thread that manages a set of read/write locks, making sure only one segment has a write lock available at a time:
public class TrafficLight {
private final ReadWriteLock[] locks;
private final Thread changer;
public TrafficLight(int segments, long changeFrequency, TimeUnit unit) {
// create and populate lock array
locks = new ReadWriteLock[segments];
Arrays.setAll(locks, i -> new ReentrantReadWriteLock(true));
CountDownLatch initialized = new CountDownLatch(1);
changer = new Thread(() -> {
// lock every segment besides the first
for (int i = 1; i < locks.length; i++) {
locks[i].writeLock().lock();
}
initialized.countDown();
int current = 0;
try {
while (true) {
unit.sleep(changeFrequency);
// lock the current segment and cycle to the next
locks[current].writeLock().lock();
current = (current + 1) % locks.length;
locks[current].writeLock().unlock();
}
} catch (InterruptedException e) {}
});
changer.setDaemon(true);
changer.start();
// wait for the locks to be initialized
awaitUninterruptibly(initialized);
}
public void enter(int segment) {
locks[segment].readLock().lock();
}
public void exit(int segment) {
locks[segment].readLock().unlock();
}
public void shutdown() {
changer.interrupt();
}
}
Now let's tweak the test code:
TrafficLight lock = new TrafficLight(segments, 100, TimeUnit.MILLISECONDS);
The result is an orderly pattern:
000111112222200000111112222200
Notes:
awaitUninterruptibly() and sleepUninterruptibly() are Guava helper methods to avoid handling InterruptedException. Feel free to copy the implementation if you don't want to import the library.
TrafficLight could be implemented by delegating state management to visiting threads, instead of relying on a background thread. This implementation is simpler (I think), but it does have some extra overhead and it requires a shutdown() to be garbage collected.
The test code uses parallel streams for convenience, but depending on your environment, it may not interleave very well. You can always use proper threads instead.
You could keep track of what mode you're in, and how many operations of that type are in progress, then only flip the mode when all of those operations are complete, eg:
public class MsLunch {
private enum LockMode {IDLE, C1_ACTIVE, C2_ACTIVE};
private LockMode lockMode = IDLE:
private int activeThreads = 0;
private long c1 = 0;
private long c2 = 0;
public void inc1() {
try {
enterMode(C1_ACTIVE);
c1++
} finally {
exitMode();
}
}
public void inc2() {
try {
enterMode(C2_ACTIVE);
c2++
} finally {
exitMode();
}
}
private synchronized void enterMode(LockMode newMode){
while(mode != IDLE && mode != newMode) {
try {
this.wait(); // don't continue while threads are busy in the other mode
} catch(InterruptedException e) {}
}
mode = newMode;
activeThreads++;
}
private synchronized void exitMode(){
activeThreads--;
if (activeThreads == 0) {
mode = IDLE;
this.notifyAll(); // no more threads in this mode, wake up anything waiting
}
}
}

How to restrict specific number of threads to synchronized block in java

I am not able to figure out this question. In a multi threaded environment - exactly 3 threads should be able to execute the synchronized block and rest should wait ?
What I understand is when we use synchronization or monitor one thread will wait until the other thread finishes its execution in side synchronized block or method. To achieve multiple thread to enter inside synchronized block or method we need to use wait(), notify(), notifyAll() i.e. inter thread communication, where wait() method when called on certain object it will takes its lock and give chances to other waiting threads.
So, I am wondering how to do the above question. I am not sure if I have put my question in right way. If its possible do we need to use java concurrent util package or can it be done in basic(core) thread functionality.
Use a semaphore with three permits:
Semaphores are often used to restrict the number of threads that can
access some (physical or logical) resource.
Using a semaphore would probably be the best solution to your problem, but it doesn't hurt to try your own solution, even though it's just for the sake of experimenting and maybe learning something new.
Here is a quick example of a lock implementation using LinkedBlockingQueue. This lock will only allow a certain number of threads to access the block of code between getKey() and returnKey():
public class Lock {
private int keys;
private LinkedBlockingQueue<Integer> q;
public Lock(int keys) throws InterruptedException {
q = new LinkedBlockingQueue<>();
while (q.size() != keys)
q.put(0);
}
public void getKey() throws InterruptedException {
q.take();
}
public void returnKey() throws InterruptedException {
q.put(0);
}
static Lock lck;
public static void main (String [] args) throws InterruptedException {
lck = new Lock(3);
Runnable r = new Runnable() {
#Override
public void run() {
try {
lck.getKey();
Lock.test();
lck.returnKey();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
for (int t = 0; t < 10; t ++)
new Thread(r).start();
}
public static void test() throws InterruptedException {
System.out.println("I am " + Thread.currentThread().getName());
Thread.sleep(1000);
}
}

Locking all the strings in a collection

I have a collection of strings which must be locked upon by a thread for computing some information. These strings are nothing but unique entities which must be handled by only one thread at a time. Any thread other than the current thread trying to acquire lock on any of these entities in the collection must wait for the current thread to complete its execution and release the lock on the collection. Two entirely different collection containing different strings can be worked upon by two different threads concurrently. I am stuck how to implement this. I tried googling. But all I found was how to lock a single string not many strings. Any idea would be helpful.
For example,
Thread one is working on apple, oranges and bananas.
Thread two wants to works on apple and peaches.
Thread two must wait until Thread one releases the lock.
Update:
Instead of looking upon the lock literally think of it as a permit to use the entity. For example, if you need to use apple, you must acquire permission. The thread must block until it gets permission for all the entities in its collection.
Let met put it in this way. Thread1 [apples, oranges, bananas] seeks permission to use the entities in the collection to a Manager. Lets assume the manager gave permission to Thread1. If another thread Thread2 [apples, peaches] seeks permission, the Manager should not give permission since permission for apples is already owned by Thread1 and Thread2 must be blocked. Once Thread1 tells the manager that it has completed its work, the Manager can give permission to Thread2. Meanwhile, if another thread Thread3 [guava, pineapple] seeks permission, the Manager should not block it and grant permission readily.
Instead of operating on many lock I would choose one synchronized storage of "locked" Strings.
That would hugely simplify synchronization.
Something like that:
private final Set<String> elementsInProgress = new HashSet<String>(); // not thread-safe, accessed only from blocks synchronized on it
public void process(Collection<String> input) throws InterruptedException {
for (String stringToProcess : input) {
synchronized (elementsInProgress) {
while (elementsInProgress.contains(stringToProcess)) {
elementsInProgress.wait();
}
elementsInProgress.add(stringToProcess);
}
doProcess(stringToProcess);
synchronized (elementsInProgress) {
elementsInProgress.remove(stringToProcess);
elementsInProgress.notifyAll();
}
}
}
private void doProcess(String s){/* ... */}
The code snippet is untested, btw )
How about starting with guava-libraries
import com.google.common.collect.Interners;
import com.google.common.collect.Interner;
Then create an an interner. Weak references are OK b/c it's the particular instance that holds the lock. You could use a ConcurrentMap (careful to use putIfAbsent) to do your interning, but...
Interner<String> namedLocks = Interners.newWeakInterner();
Then the client threads can simply use synchronized. I'm using Callable to represent the work.
public <T> void doWork(String name, Callable<T> work) {
synchronized(namedLocks.intern("name")) {
return work.call();
}
}
This will work if Thread 1 (apple, oranges, bananas) and Thread 2 (apple, peaches) can work on (for example) "oranges" and "peaches" concurrently. The 'work' variable in this case represents the work of 'oranges' independently.
If Thread 2 must wait until Thread 1 is done with all three items before starting any of its own, then it's a bit more complex but still manageable. The 'work' in this case represents 'apple+oranges+bananas'.
public <T> T doWork(List<String> names, Callable<T> work) {
// important to avoid deadlocks
names = new ArrayList<>(names);
Collections.sort(names);
return doWorkInternal(names.iterator());
}
private <T> T doWorkInternal(Iterator<String> names, Callable<T> work) {
if(names.hasNext()) {
synchronized(namedLocks.intern(names.next())) {
return doWorkInternal(names, work);
}
} else { // no more locks to acquire
return work.call();
}
}
In the above, you're acquiring each lock in sorted order (important for deadlock) as you recurse down the stack.
public class FruitRunnable implements Runnable {
// this is the actual lock
private static final Object lock = new Object();
// here we store which objects are currently used
private static final Set<String> usedObjects = new HashSet<String>();
// these are the objects a thread will need
private final String[] neededObjects;
public FruitRunnable(String... neededObjects) {
this.neededObjects = neededObjects;
}
#Override
public void run() {
acquireLock(neededObjects);
// between these two methods we can assure that there is
// no other thread working on our resources
work();
// important! release the resources afterwards!
releaseLock(neededObjects);
}
private void work() {
System.out.println("working: " + Arrays.toString(neededObjects));
try {
// work of 10 seconds
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void acquireLock(String[] fruits) {
// go into lock
synchronized (lock) {
// loop until we can acquire our resources
boolean success = false;
while (!success) {
success = true;
for (String s : fruits) {
if (usedObjects.contains(s)) {
// too bad this fruit is already in use
success = false;
}
}
// on success add all used fruits to the usedObjects Set and return
if (success) {
for (String s : fruits) {
usedObjects.add(s);
}
return;
}
// if we had no success we will wait until some other thread
// releases fruits
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void releaseLock(String[] fruits) {
synchronized (lock) {
// release the fruits and notify the other threads to re-check
for (String s : fruits) {
usedObjects.remove(s);
}
lock.notifyAll();
}
}
public static void main(String[] args) throws InterruptedException {
// starting the threads from your example
new Thread(new FruitRunnable("apple", "oranges", "bananas")).start();
new Thread(new FruitRunnable("apple", "peaches")).start();
Thread.sleep(2000);
new Thread(new FruitRunnable("guava", "pineapple")).start();
}
}
Find some comments on how it works in code.

Categories