Locking all the strings in a collection - java

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.

Related

(Java) Thread safety using Object wait() and notify()

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.

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.

Fine-tuning Java synchronized block behavior

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();
}
}
}

Sharing an ArrayList between two threads?

So I have two threads running where one of them is supposed to get information from the user and the other thread is suppose to work with information supplied by users as follows:
public class UserRequest implements Runnable {
#Override
public void run() {
// TODO Auto-generated method stub
String request;
Scanner input = new Scanner(System.in);
while(true)
{
System.out.println("Please enter request:");
request = input.nextLine();
try
{
//do something
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
And second thread:
public class Poller implements Runnable {
ArrayList<String> colors = new ArrayList<String>();
public void poll()
{
for(String color : colors)
{
if(color == "")
{
//do work
}
else
{
//do work
}
}
}
#Override
public void run() {
colors.add("Violet");
colors.add("Green");
colors.add("Yellow");
colors.add("Orange");
while(true)
poll();
}
}
What I would like to do is take whatever input the user entered inside the UserRequest object and push into the ArrayList in Poller object so it can "work" on the new value as well. I have looked at some thing like BlockingQueue but I don't want either Thread to wait for the other since they have other tasks they need to accomplish in addition to this sharing of data. How can I go about doing this ?
Since you've used the verb 'push' and 'poll', it seems you are looking for a Queue not a List.
Therefore, I think you're looking for the ConcurrentLinkedQueue, documented here.
It allows you to have your UserRequest objects feed it and your Poller objects to consume it.
Though it seems your Poller objects will have quite a high CPU consuption because of the open while not having any wait:
public class Poller implements Runnable {
Queue<String> colors = new ConcurrentLinkedQueue<String>();
public void poll() {
while(this.colors.isEmpty()){
Thread.currentThread().wait();
}
String color = this.colors.poll();
while(color != null) {
if(color == "") {
//do work
} else {
//do work
}
color = this.colors.poll();
}
}
#Override
public void run() {
colors.offer("Violet");
colors.offer("Green");
colors.offer("Yellow");
colors.offer("Orange");
while(true) {
this.poll();
}
}
}
this code needs some changes to run but it contains pretty much everything you need.
What it does is very simple: It keeps polling until there are no elements left.
Once that happens, the Poller object asks it's current Thread to sleep, since there's no point for it to run without elements in the Queue.
public class UserRequest implements Runnable {
#Override
public void run() {
String request;
Scanner input = new Scanner(System.in);
while(true) {
System.out.println("Please enter request:");
request = input.nextLine();
try {
//do something
} catch(IOException e) {
e.printStackTrace();
} finally {
this.notifyAll(); // Notifies all sleeping threads to wake up
}
}
}
If you notice, I've only added a notifyAll call to your UserRequest class. Why? Very simple: notifyAll wakes all waiting Threads which is exactly what all Pollers without elements are doing.
Once it's called, the Pollers will wake, check if their color Queue has elements and work with them. If the Queue has no elements, they will sleep again until a UserRequest wakes them up again and so on and so forth.
There are two ways to solve this problem:
1) It's using thread safe collection, like ConccurentLinkedQueue for logic with producer-consumer, jobs consuming or etc. If you want to use the class that implements List interface (and as a consequence you can take methods same to usual ArrayList), you must look to the side of CopyOnWriteArrayList, but note that this class uses blocking synchronization.
2) Another approach is using built-in java synchronization tools, for example
Semaphore
CyclicBarrier
CountDownLatch
Locks
Phaser
Usual wait/notify mechanism
For more details, you must read the specification. Let's consider an example of using Semaphore:
private final Semaphore semaphore = new Semaphore(2, true);
public void appendToList() throws InterruptedException {
available.acquire();
arrayList.add(.....); //put here what u need
}
public void putItem(Object x) {
if (someLogicHere(x)) //semaphore releases counter in this place
available.release();
}
Of course, you can combine usage all of them, e.g. you can use a few semaphores simultaneously, or use diff tools.
"but I don't want either Thread to wait for the other since they have other tasks they need to accomplish in addition to this sharing of data."
There's no way to accomplish this. Any proper threading of the class will always suffer from the problem that you will need to have one thread wait while the other does something. The point though is you want to minimize that. You want to only cause the thread to stall very briefly and rarely and only in those cases where not doing so will cause it to fault. You can use one of the synchronized data structures or you can just write a little bit of synchronization code yourself.
The only object in question is the arraylist, and you want the absolute minimum amount of stall on either thread. So you would want to synchronize it based on the object of the arraylist itself. So just write a couple little synchronization blocks around the points where you access the arraylist object.
public class Poller implements Runnable {
ArrayList<String> colors;
public Poller(ArrayList<String> colors) {
this.colors = colors;
//pass in colors object, if modified from the scanner side it must synchronize the block around the colors object too.
}
public void doWork(String color) {
//do work
}
public void addColor(String color) {
synchronized (colors) {
colors.add(color);
}
}
#Override
public void run() {
while (!Thread.interrupted())
if (!colors.isEmpty()) {
String color;
synchronized (colors) {
color = colors.remove(0);
}
doWork(color); //work done outside synch
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The point is just never be removing or adding things to the list at the same time. You cannot loop over the list as a whole because if the work is done in-loop it's a problem and the size of the array might change so you don't know how bit it is. But, you can use an ArrayList for this, just synchronize the blocks of code where you change the datastructure and get the string out of that synchronized block and then do work on it. This way the only stall is the brief instant one thread is reading or writing and the other one needs to. Both of which are very fast operations.
If you want access new value entered by the user from poller object then:
As objects are stored in heap , instead of creating a new instance of arrayList in the Poller class you could just send a reference of list object from the UserRequest.So that when yu change add new value to arrayList in userRequest it will be reflected in arrayList being used by Poller.
For Example, You can do it this way:
public class UserRequest implements Runnable {
private ArrayList<String> arrayList = new ArrayList<String>();
#Override
public void run() {
// TODO Auto-generated method stub
String request;
Scanner input = new Scanner(System.in);
while(true)
{
System.out.println("Please enter request:");
request = input.nextLine();
try
{
Poller poller = new Poller(arrayList);
Thread t = new Thread(poller);
t.start();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
You can change your Poller class like this:
public class Poller implements Runnable {
private ArrayList arrayList = null;
Poller(ArrayList<String> arrayList){
this.arrayList = arrayList;
}
public void poll()
{
for(String color : arrayList)
{
if(color == "")
{
//do work
}
else
{
//do work
}
}
}
#Override
public void run() {
while(true){
poll();
}
}
But instead of calling pool in a infinity loop you should add a listener to your arrayList so that you call poll() only when a new value has been added to the List.
You can check out this link to know more about adding listener to a ArrayList: https://stackoverflow.com/a/16529462/7083385
You can use a queue. A queue has its own poll method. You could make it static but i doubt that is the best approach. Generally I use spring to instantiate the queue in some kind of wrapper class but it doesnt look like you are taking that route.

Do I need synchronise on objects which guarantee happen-before?

I have a collection which guaranteed to be visible across threads. However that doesn't guarantee visibility of states of items which are stored in this collection(eg. if I have collection of StringBuilder(mutable, not thread safe) then I have to synchronize on each item in collection during write/read, right?). So, what happens when I have collection of objects which are used for guaranteeing happen-before by themselves(eg. countdownlatch). Do I need to synchronize on each item somehow when calling await/countDown? Code below roughly illustrate this dilemma:
public class SyncQuestion {
final List<CountDownLatch> lathces = new ArrayList<CountDownLatch>();
SyncQuestion() {
lathces.add(new CountDownLatch(1));
}
public static void main(String[] args) throws InterruptedException {
final SyncQuestion sync = new SyncQuestion();
final Thread sleepingThread = new Thread() {
public void run() {
for (CountDownLatch latch : sync.lathces) {
try {
latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
};
};
final Thread wakingThread = new Thread() {
public void run() {
for (CountDownLatch latch : sync.lathces) {
latch.countDown();
}
};
};
sleepingThread.start();
wakingThread.start();
sleepingThread.join();
wakingThread.join();
}
}
Please correct me in my assumptions, if they are wrong.
A CountDownLatch is basically a wrapper on AbstractQueuedSynchronizer whose state is a volatile int that is mutated via Unsafe.compareAndSwapInt (which is an atomic operation).
Therefore in this specific case, as Cameron Skinner said, there is no need to synchronize because it enforces that happens-before for you.
I don't believe you need to manually synchronize in this case because the latches are internally thread-safe.

Categories