What happens when few threads trying to call the same synchronized method? - java

so I got this horses race and when a horse getting to the finishing line, I invoke an arrival method. Let's say I got 10 threads, one for each horse, and the first horse who arrives indeed invoking 'arrive':
public class FinishingLine {
List arrivals;
public FinishingLine() {
arrivals = new ArrayList<Horse>();
}
public synchronized void arrive(Horse hourse) {
arrivals.add(hourse);
}
}
Ofc I set the arrive method to synchronized but I dont completely understand what could happen if it wasnt synchronized, the professor just said it wouldn't be safe.
Another thing that I would like to understand better is how it is decided which thread will after the first one has been finished? After the first thread finished 'arrive' and the method get unlocked, which thread will run next?

1) It is undefined what the behaviour would be, but you should assume that it is not what you would want it to do in any way that you can rely upon.
If two threads try to add at the same time, you might get both elements added (in either order), only one element added, or maybe even neither.
The pertinent quote from the Javadoc is:
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.)
2) This is down to how the OS schedules the threads. There is no guarantee of "fairness" (execution in arrival order) for regular synchronized blocks, although there are certain classes (Semaphore is one) which give you the choice of a fair execution order.
e.g. you can implement a fair execution order by using a Semaphore:
public class FinishingLine {
List arrivals;
final Semaphore semaphore = new Semaphore(1, true);
public FinishingLine() {
arrivals = new ArrayList<Horse>();
}
public void arrive(Horse hourse) {
semaphore.acquire();
try {
arrivals.add(hourse);
} finally {
semaphore.release();
}
}
}
However, it would be easier to do this with a fair blocking queue, which handles the concurrent access for you:
public class FinishingLine {
final BlockingQueue queue = new ArrayBlockingQueue(NUM_HORSES, true);
public void arrive(Horse hourse) {
queue.add(hourse);
}
}

Related

Java wait() and notifyAll() resume oldest Thread

My problem:
Lets say that i have class A with some variable a
And class B with variables prev and next
In class A i want to make method changeIfEqual(B myB) which checks if A.a == my_B.prev, if so i change A.a to my_B.next. But if A.a != my_B.prev i want thread to wait() until continion is true and then execute the thread that have been waining for the longest time.
So I imagine A.changeIfEqual(B myB) should look like this:
public synchronized void changeIfEqual(B myB){
while(this.a != myB.b_prev){
wait();
}
notifyAll();
}
In this case the problem is how can I ensure that the oldest thread would be resume? (wait() and notifyAll() dont provide that)
You don’t. Which thread gets notified is up to the scheduler. If you replace the implicit locking (using synchronized) with ReentrantLock, then you can specify that the lock is fair. But that's not a perfect solution, see the API docs:
The constructor for this class accepts an optional fairness parameter. When set true, under contention, locks favor granting access to the longest-waiting thread. Otherwise this lock does not guarantee any particular access order. Programs using fair locks accessed by many threads may display lower overall throughput (i.e., are slower; often much slower) than those using the default setting, but have smaller variances in times to obtain locks and guarantee lack of starvation. Note however, that fairness of locks does not guarantee fairness of thread scheduling. Thus, one of many threads using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock. Also note that the untimed tryLock method does not honor the fairness setting. It will succeed if the lock is available even if other threads are waiting.
If you absolutely must wake "consumer" threads in a particular order,* the thing to do would be to give each consumer its own Semaphore, and have each consumer put a reference to its semaphore into a queue before awaiting it.
class MyConsumer {
private final Queue<Semaphore> sleep_q;
private final Semaphore sleep_sem = new Semaphore(0);
public MyConsumer(Queue sleep_q) {
this.sleep_q = sleep_q;
}
private void waitToBeNotified() {
sleep_q.add(sleep_sem);
sleep_sem.acquire();
}
public void whatever() {
doSomeStuff();
waitToBeNotified();
doSomeMoreStuff();
}
The producer can awaken the longest-waiting thread by popping a semaphore from the queue, and releasing a permit to it.
class MyProducer {
private final Queue<Semaphore> sleep_q;
public MyConsumer(Queue sleep_q) {
this.sleep_q = sleep_q;
}
public void goForthAndProduceStuff() {
while (...) {
produceSomething();
awakenAConsumer();
}
}
private void awakenAConsumer() {
Semaphore sem = sleep_q.poll();
if (sem != null) {
sem.release();
}
}
}
* But, see my comment on the original question.

Check size and then perform operation - is it safe for ConcurrentLinkedDeque?

I need to replace the first value in Deque with the new value, only
if the size will exceed the limit. I wrote this code to solve it:
final class Some {
final int buffer;
final Deque<Operation> operations = new ConcurrentLinkedDeque<>();
// constructors ommited;
#Override
public void register(final Operation operation) {
if (this.operations.size() == this.buffer) {
// remove the oldest operation
this.operations.removeFirst();
}
// add new operation to the tail
this.operations.addLast(operation);
}
#Override
public void apply() {
// take the fresh operation from tail and perform it
this.operations.removeLast().perform();
}
}
As you see, I have two methods, that modifies the Deque. I have doubts, that this code will work correctly in the multithreaded environment. The question is: is it safe to check the size() and then performing operations, that modifies the ConcurrentLinkedDeque afterward? I want to have as least locks as possible. So if this code won't work, then I had to introduce locking and then there is no point in the usage of ConcurrentLinkedDeque().
final class Some {
final int buffer;
final Deque<Operation> operations = new LinkedList<>();
final Lock lock = new ReentrantLock();
// constructors ommited;
#Override
public void register(final Operation operation) {
this.lock.lock();
try {
if (this.operations.size() == this.buffer) {
// remove the oldest operation
this.operations.removeFirst();
}
// add new operation to the tail
this.operations.addLast(operation);
} finally {
lock.unlock();
}
}
#Override
public void apply() {
this.lock.lock();
try {
// take the fresh operation from tail and perform it
this.operations.removeLast().perform();
} finally {
this.lock.unlock();
}
}
}
This is the alternative with the Lock. Is that the only way to achieve what I want? I am especially interested in trying to use the concurrent collections.
Concurrent collections are thread-safe when it comes to internal state. In other words, they
Allow multiple threads to read/write concurrently without having to worry that the internal state will become corrupted
Allow iteration and removal while other threads are modifying the collection
Not all, however. I believe CopyOnWriteArrayList's Iterator does not support the remove() operation
Guarantees things such as happens-before
Meaning a write by one thread will happen-before a read by a subsequent thread
However, they are not thread-safe across external method calls. When you call one method it will acquire whatever locks are necessary but those locks are released by the time the method returns. If you're not careful this can lead to a check-then-act race condition. Looking at your code
if (this.operations.size() == this.buffer) {
this.operations.removeFirst();
}
this.operations.addLast(operation);
the following can happen:
Thread-A checks size condition, result is false
Thread-A moves to add new Operation
Before Thread-A can add the Operation, Thread-B checks size condition which results in false as well
Thread-B goes to add new Operation
Thread-A does add new Operation
Oh, no! The Operation added by Thread-A causes the size threshold to be reached
Thread-B, already past the if statement, adds its Operation making the deque have one too many Operations
This is why a check-then-act requires external synchronization, which you do in your second example using a Lock. Note you could also use a synchronized block on the Deque.
Unrelated to your question: You call Operation.perform() in your second example while still holding the Lock. This means no other thread can attempt to add another Operation to the Deque while perform() executes. If this isn't desired you can change the code like so:
Operation op;
lock.lock();
try {
op = deque.pollLast(); // poll won't throw exception if there is no element
} finally {
lock.unlock();
}
if (op != null) {
op.perform();
}
From the doc of size()
BlockquoteBeware that, unlike in most collections, this method is NOT a constant-time operation. Because of the asynchronous nature of these deques, determining the current number of elements requires traversing them all to count them. Additionally, it is possible for the size to change during execution of this method, in which case the returned result will be inaccurate. Thus, this method is typically not very useful in concurrent applications.
While #Slaw is correct, also add that an addition/subtraction can occur during the traversal.
I don't use size() in my software. I keep my own count of what is in the collection with an AtomicInteger. If count.get() < max, I can add. Being a little over max is ok for my usage. You can use a lock on count to force compliance.

Could you explain me one thing about synchronization in Java?

Imagine that we have multithreading application and a class with the following variable and method:
private List list = new ArrayList();
public void doNothing() {
synchronized (list) {
list.get(0);
String stuff = "Stuff";
list.get(0);
}
}
Am I right that when one thread processes method doNothing() it loses monitor on String stuff = "Stuff"; and the output of list.get(0); may be different because other thread can modify the list?
Yes, you are right, but not because the monitor is lost on handling the stuff string. The fact that you synchronized on the list does not prevent another thread to change it. The only way to enforce the list being unchanged between the two gets is to have all threads changing the list run that code inside a synchronized(list). Also, having a Synchronized list will not help in your case.
Only one thread at a time can work in synchronized block. But if any other thread modifies the list in for example some other function then of course, output of list.get(0) can differ between invocations. String stuff due to being created in this block can't be changed by any other thread than the one that is currently running through it.
Only one thread can execute inside a Java code block synchronized on the same monitor object.
The thread only "loses the monitor" once it reaches the end of the synchronized block.
In your specific case, the result from calling list.get(0); can be the same or not, depending on other threads that can invoke the mutators on that list outside any code block synchronized on the list object.
The purpose of the synchronization objects is to allow you to synchronize more than one block on the same lock.
In the following example only one thread can execute inside any of the two blocks at the same time:
public void doNothing() {
synchronized (list) {
//someStuff
}
}
public void doSomething() {
synchronized (list) {
//anotherStuff
}
}

Non blocking function that preserves order

I have the following method:
void store(SomeObject o) {
}
The idea of this method is to store o to a permanent storage but the function should not block. I.e. I can not/must not do the actual storage in the same thread that called store.
I can not also start a thread and store the object from the other thread because store might be called a "huge" amount of times and I don't want to start spawning threads.
So I options which I don't see how they can work well:
1) Use a thread pool (Executor family)
2) In store store the object in an array list and return. When the array list reaches e.g. 1000 (random number) then start another thread to "flush" the array list to storage. But I would still possibly have the problem of too many threads (thread pool?)
So in both cases the only requirement I have is that I store persistantly the objects in exactly the same order that was passed to store. And using multiple threads mixes things up.
How can this be solved?
How can I ensure:
1) Non blocking store
2) Accurate insertion order
3) I don't care about any storage guarantees. If e.g. something crashes I don't care about losing data e.g. cached in the array list before storing them.
I would use a SingleThreadExecutor and a BlockingQueue.
SingleThreadExecutor as the name sais has one single Thread. Use it to poll from the Queue and persist objects, blocking if empty.
You can add not blocking to the queue in your store method.
EDIT
Actually, you do not even need that extra Queue - JavaDoc of newSingleThreadExecutor sais:
Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.
So I think it's exactly what you need.
private final ExecutorService persistor = Executors.newSingleThreadExecutor();
public void store( final SomeObject o ){
persistor.submit( new Runnable(){
#Override public void run(){
// your persist-code here.
}
} );
}
The advantage of using a Runnable that has a quasi-endless-loop and using an extra queue would be the possibility to code some "Burst"-functionality. For example you could make it wait to persist only when 10 elements are in queue or the oldest element has been added at least 1 minute ago ...
I suggest using a Chronicle-Queue which is a library I designed.
It allows you to write in the current thread without blocking. It was originally designed for low latency trading systems. For small messages it takes around 300 ns to write a message.
You don't need to use a back ground thread, or a on heap queue and it doesn't wait for the data to be written to disk by default. It also ensures consistent order for all readers. If the program dies at any point after you call finish() the message is not lost. (Unless the OS crashes/loses power) It also supports replication to avoid data loss.
Have one separate thread that gets items from the end of a queue (blocking on an empty queue), and writes them to disk. Your main thread's store() function just adds items to the beginning of the queue.
Here's a rough idea (though I assume there will be cleaner or faster ways for doing this in production code, depending on how fast you need things to be):
import java.util.*;
import java.io.*;
import java.util.concurrent.*;
class ObjectWriter implements Runnable {
private final Object END = new Object();
BlockingQueue<Object> queue = new LinkedBlockingQueue();
public void store(Object o) throws InterruptedException {
queue.put(o);
}
public ObjectWriter() {
new Thread(this).start();
}
public void close() throws InterruptedException {
queue.put(END);
}
public void run() {
while (true) {
try {
Object o = queue.take();
if (o == END) {
// close output file.
return;
}
System.out.println(o.toString()); // serialize as appropriate
} catch (InterruptedException e) {
}
}
}
}
public class Test {
public static void main(String[] args) throws Exception {
ObjectWriter w = new ObjectWriter();
w.store("hello");
w.store("world");
w.close();
}
}
The comments in your question make it sound like you are unfamilier with multi-threading, but it's really not that difficult.
You simply need another thread responsible for writing to the storage which picks items off a queue. - your store function just adds the objects to the in-memory queue and continues on it's way.
Some psuedo-ish code:
final List<SomeObject> queue = new List<SomeObject>();
void store(SomeObject o) {
// add it to the queue - note that modifying o after this will also alter the
// instance in the queue
synchronized(queue) {
queue.add(queue);
queue.notify(); // tell the storage thread there's something in the queue
}
}
void storageThread() {
SomeObject item;
while (notfinished) {
synchronized(queue) {
if (queue.length > 0) {
item = queue.get(0); // get from start to ensure same order
queue.removeAt(0);
} else {
// wait for something
queue.wait();
continue;
}
}
writeToStorage(item);
}
}

Queue of Thread objects

I am trying to have some Threads on a Queue so I can manage them from there. Is this possible? I have some code but it don't work correctly.
The main idea is to generate X threads and put every thread inside a queue in another class. Then in the class who have the queue use wait() and notify() methods to have a FIFO execution order.
Thanks in advance.
Some of the code:
public synchronized void semWait(Thread petitionerThread){
count--;
if(count < 0){
try {
petitionerThread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
FIFOQueue.add(petitionerThread);
}
}
public synchronized void semSignal(Thread noticeThread){
count++;
if(count <= 0)
if(!FIFOQueue.isEmpty())
FIFOQueue.pollLast().notify();
}
Edit: The problem is that when a Thread enters the queue and it is put to wait, something happen that the semSignal method is never executed for any of the other threads (its called after semWait()).
You might want to check BlockingQueue(concrete class LinkedBlockingQueue) in java. This queue allows you to put any object into it, for that matter even Thread. The queue.put() will wait if the queue is full. And queue.get() will wait if queue is empty. wait() and notify() are implicitly taken care of.
Then a set of threads can take from the queue and execute them in order.
We are talking of a producer-consumer problem.
Your code violates one basic programming rule: let object governs itself. First, code that waits/notifies should be inside the methods of that object. Then, if you want a thread to behave some way, program its run method accordingly. In the code, you try to manipulate threads as if they are ordinary objects, while they are not. Low-level code which treats thread as objects is implemented already in wait/notify/synchronized and whatever synchronization primitives, and you need not to reimplement the wheel, unless you make a new operating system.
Looks like you are trying to implement Semaphore. In this case, your methods need not parameters. semWait should place in the queue current thread, and semSignal release a thread from the queue and not the thread passed as argument.
One possible implementation is as follows:
class Sem {
int count;
public synchronized void semWait() throws InterruptedException {
while (count <= 0) {
wait();
}
count--;
}
public synchronized void semSignal() {
count++;
notify();
}
}

Categories