Seat booking using synchronized block - java

I am trying to implement seat booking validation using a synchronized block like this:
synchronized(this) {
int seatsBooked = GrantAssessment.countByExamSessionAndExamDateBetweenAndIsCancelled(examSession,now,now+1,false)
int seatsRemaining = examSession.maxSeat - seatsBooked
if(seatsRemaining<1){
throw new CustomValidationException("All seats booked...")
}
// assign assessment which increases countByExam... query count by 1
grantAssessment = assignAssessment(examCommerce,examSession,examDate,identificationType,idNumber)
}
assignAssessment() method code is as follows:
def assignAssessment(ExamCommerce examCommerce, ExamSession examSession,Date examDate,IdentificationType identificationType,String idNumber) {
.................
examSession.addToGrantAssessmentList(grantAssessment)
..............................
grantAssessment.save(failOnError: true,flush: true)
examSession.save(failOnError: true,flush: true)
return grantAssessment
}
When I hit using browser 1(different thread) it enters the synchornized block and assigns a seat. When browser 2(thread 2, almost same time) enters the block the query count returned by the code below :
GrantAssessment.countByExamSessionAndExamDateBetweenAndIsCancelled(examSession,now,now+1,false)
is same.But the same thread shows reduced value(correct) after synchronized block.
Due to this, both the threads assigns the seat even if totalSeat is equal to 1.
How to handle to concurrency such that availableSeats value should be calculated correctly in a synchronized way. Is JMS OK for such scenarios ?

Seems like you are using different monitors.
For example the following can lead to the same state as you described both the threads assigns the seat even if totalSeat is equal to 1.
private static ExecutorService executorService = Executors.newFixedThreadPool(2);
boolean bookTwoSeatsInParallel() {
Future<Integer> res1 = executorService.submit(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
synchronized(this) {
//your seat booking code which returns seat num or whatever
}
return -1;
}
});
Future<Integer> res2 = executorService.submit(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
synchronized(this) {
//your seat booking code which returns seat num or whatever
}
return -1;
}
});
}
res1.get().equals(res2.get()) could be true. This example is a bit redundant but it shows the case when different threads use different monitors in a try to achieve valid synchronized state.
To fix this you should synchronize on the same monitor, like this
private static ExecutorService executorService = Executors.newFixedThreadPool(2);
private final Object bookingMonitor = new Object();
boolean bookTwoSeatsInParallel() {
Future<Integer> res1 = executorService.submit(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
synchronized(bookingMonitor) {
//your seat booking code which returns seat num or whatever
}
return -1;
}
});
Future<Integer> res2 = executorService.submit(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
synchronized(bookingMonitor) {
//your seat booking code which returns seat num or whatever
}
return -1;
}
});
}
Note that all variables you read/modify inside the synchronized(this) {...} block shouldn't be read/modified from somewhere else without synchronization on the same monitor. In other case it can lead to Thread Interference and Memory Consistency Errors
Is JMS OK for such scenarios ?
Definitely you can use JMS, pass booking requests through it to the only worker thread. But you don't need such a complex solution for this simple case.

Related

How to fix async java code failing even with thread safety implementation?

I am working on a codebase that implements something similar to this. We are having issues with one of the threads failing to synchronize with other threads when the value of count is incremented, thus going into an infinite loop.
The problem seems to come from the non-atomic behaviour of the post-increment operator.
You can find the code Repl here NB: You may need to run the code at least 3 times to observe it.
I need support to implement increment of count by as many threads as possible in a thread safety way.
class Main {
static volatile Integer count = new Integer(0); //boxed integer is intentional to demonstrate mutable instance
static final void Log(Object o) {
System.out.println(o);
}
static synchronized void increaseCount(){
count++;
}
static synchronized Integer getCount(){
return count;
}
public static void main(String[] arg) throws InterruptedException {
new Thread(() -> {
while (getCount() != 60) {
increaseCount();
Log(count +" thread A");
}
}).start();
new Thread(() -> {
while (getCount() != 20) {
increaseCount();
Log(count +" thread B");
}
}).start();
new Thread(() -> {
while (getCount() != 50) {
increaseCount();
Log(count+" thread C");
}
}).start();
}
}
If many threads are incrementing a shared counter, there is no guarantee about which thread will see a particular value of the counter. To make sure a particular thread sees a particular value, that thread has to see every value of the counter. And then you might as well just have one thread, because they are all working in lockstep with each other.
If you want to do some work for every value of the counter, with special handling for particular values, and you want to parallelize that workload, every thread needs to be prepared to perform the special handling. Here's an example of how you could do that:
class Main {
private static class Worker implements Runnable {
private final AtomicInteger counter;
private final Set<Integer> triggers;
Worker(AtomicInteger counter, Set<Integer> triggers) {
this.counter = counter;
this.triggers = triggers;
}
public void run() {
String name = Thread.currentThread().getName();
while (!triggers.isEmpty()) {
int value = counter.getAndIncrement();
try { /* Simulate actually doing some work by sleeping a bit. */
long delay = (long) (-100 * Math.log(1 - ThreadLocalRandom.current().nextDouble()));
TimeUnit.MILLISECONDS.sleep(delay);
} catch (InterruptedException ex) {
break;
}
boolean triggered = triggers.remove(value);
if (triggered) {
System.out.println(name + " handled " + value);
} else {
System.out.println(name + " skipped " + value);
}
}
}
}
public static void main(String[] arg) throws InterruptedException {
AtomicInteger counter = new AtomicInteger();
Set<Integer> triggers = new ConcurrentSkipListSet<>();
triggers.add(60);
triggers.add(20);
triggers.add(50);
int concurrency = 4;
ExecutorService workers = Executors.newFixedThreadPool(concurrency);
for (int i = 0; i < concurrency; ++i) {
workers.execute(new Worker(counter, triggers));
}
workers.shutdown();
}
}
The number of worker threads can be adjusted so that it makes sense given the number of cores on your machine, and the real workload (how CPU or I/O intensive the tasks are).
In this approach, each value of the counter is processed by just one thread, and it doesn't matter which thread gets a "sentinel" value. But, when all the sentinel values have been processed, all the threads shut down. Threads coordinate with each other through the counter, and the set of "triggers", or sentinel values that they need to handle.

Java Producer Consumer ArrayBlockingQueue deadlock on take()

In my app there are 2 phases, one download some big data, and the other manipulates it.
so i created 2 classes which implements runnable: ImageDownloader and ImageManipulator, and they share a downloadedBlockingQueue:
public class ImageDownloader implements Runnable {
private ArrayBlockingQueue<ImageBean> downloadedImagesBlockingQueue;
private ArrayBlockingQueue<String> imgUrlsBlockingQueue;
public ImageDownloader(ArrayBlockingQueue<String> imgUrlsBlockingQueue, ArrayBlockingQueue<ImageBean> downloadedImagesBlockingQueue) {
this.downloadedImagesBlockingQueue = downloadedImagesBlockingQueue;
this.imgUrlsBlockingQueue = imgUrlsBlockingQueue;
}
#Override
public void run() {
while (!this.imgUrlsBlockingQueue.isEmpty()) {
try {
String imgUrl = this.imgUrlsBlockingQueue.take();
ImageBean imageBean = doYourThing(imgUrl);
this.downloadedImagesBlockingQueue.add(imageBean);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ImageManipulator implements Runnable {
private ArrayBlockingQueue<ImageBean> downloadedImagesBlockingQueue;
private AtomicInteger capacity;
public ImageManipulator(ArrayBlockingQueue<ImageBean> downloadedImagesBlockingQueue,
AtomicInteger capacity) {
this.downloadedImagesBlockingQueue = downloadedImagesBlockingQueue;
this.capacity = capacity;
}
#Override
public void run() {
while (capacity.get() > 0) {
try {
ImageBean imageBean = downloadedImagesBlockingQueue.take(); // <- HERE I GET THE DEADLOCK
capacity.decrementAndGet();
} catch (InterruptedException e) {
e.printStackTrace();
}
// ....
}
}
}
public class Main {
public static void main(String[] args) {
String[] imageUrls = new String[]{"url1", "url2"};
int capacity = imageUrls.length;
ArrayBlockingQueue<String> imgUrlsBlockingQueue = initImgUrlsBlockingQueue(imageUrls, capacity);
ArrayBlockingQueue<ImageBean> downloadedImagesBlockingQueue = new ArrayBlockingQueue<>(capacity);
ExecutorService downloaderExecutor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
Runnable worker = new ImageDownloader(imgUrlsBlockingQueue, downloadedImagesBlockingQueue);
downloaderExecutor.execute(worker);
}
downloaderExecutor.shutdown();
ExecutorService manipulatorExecutor = Executors.newFixedThreadPool(3);
AtomicInteger manipulatorCapacity = new AtomicInteger(capacity);
for (int i = 0; i < 3; i++) {
Runnable worker = new ImageManipulator(downloadedImagesBlockingQueue, manipulatorCapacity);
manipulatorExecutor.execute(worker);
}
manipulatorExecutor.shutdown();
while (!downloaderExecutor.isTerminated() && !manipulatorExecutor.isTerminated()) {
}
}
}
The deadlock happens because this scenario:
t1 checks capacity its 1.
t2 checks its 1.
t3 checks its 1.
t2 takes, sets capacity to 0, continue with flow and eventually exits.
t1 and t3 now on deadlock, cause there will be no adding to the downloadedImagesBlockingQueue.
Eventually i want something like that: when the capacity is reached && the queue is empty = break the "while" loop, and terminate gracefully.
to set "is queue empty" as only condition won't work, cause in the start it is empty, until some ImageDownloader puts a imageBean into the queue.
There area a couple of things you can do to prevent deadlock:
Use a LinkedBlockingQueue which has a capacity
Use offer to add to the queue which does not block
Use drainTo or poll to take items from the queue which are not blocking
There are also some tips you might want to consider:
Use a ThreadPool:
final ExecutorService executorService = Executors.newFixedThreadPool(4);
If you use a fixed size ThreadPool you can add "poison pill"s when you finished adding data to the queue corresponding to the size of your ThreadPool and check it when you poll
Using a ThreadPool is as simple as this:
final ExecutorService executorService = Executors.newFixedThreadPool(4);
final Future<?> result = executorService.submit(new Runnable() {
#Override
public void run() {
}
});
There is also the less known ExecutorCompletionService which abstracts this whole process. More info here.
You don't need the capacity in your consumer. It's now read and updated in multiple threads, which cause the synchronization issue.
initImgUrlsBlockingQueue creates the url blocking queue with capacity number of URL items. (Right?)
ImageDownloader consumes the imgUrlsBlockingQueue and produce images, it terminates when all the URLs are downloaded, or, if capacity means number of images that should be downloaded because there may be some failure, it terminates when it added capacity number of images.
Before ImageDownloader terminates, it add a marker in to the downloadedImagesBlockingQueue, for example, a null element, a static final ImageBean static final ImageBean marker = new ImageBean().
All ImageManipulator drains the queue use the following construct, and when it sees the null element, it add it to the queue again and terminate.
// use identity comparison
while ((imageBean = downloadedImagesBlockingQueue.take()) != marker) {
// process image
}
downloadedImagesBlockingQueue.add(marker);
Note that the BlockingQueue promises its method call it atomic, however, if you check it's capacity first, and consume an element according to the capacity, the action group won't be atomic.
Well i used some of the features suggested, but this is the complete solution for me, the one which does not busy waiting and wait until the Downloader notify it.
public ImageManipulator(LinkedBlockingQueue<ImageBean> downloadedImagesBlockingQueue,
LinkedBlockingQueue<ImageBean> manipulatedImagesBlockingQueue,
AtomicInteger capacity,
ManipulatedData manipulatedData,
ReentrantLock downloaderReentrantLock,
ReentrantLock manipulatorReentrantLock,
Condition downloaderNotFull,
Condition manipulatorNotFull) {
this.downloadedImagesBlockingQueue = downloadedImagesBlockingQueue;
this.manipulatedImagesBlockingQueue = manipulatedImagesBlockingQueue;
this.capacity = capacity;
this.downloaderReentrantLock = downloaderReentrantLock;
this.manipulatorReentrantLock = manipulatorReentrantLock;
this.downloaderNotFull = downloaderNotFull;
this.manipulatorNotFull = manipulatorNotFull;
this.manipulatedData = manipulatedData;
}
#Override
public void run() {
while (capacity.get() > 0) {
downloaderReentrantLock.lock();
if (capacity.get() > 0) { //checks if the value is updated.
ImageBean imageBean = downloadedImagesBlockingQueue.poll();
if (imageBean != null) { // will be null if no downloader finished is work (successfully downloaded or not)
capacity.decrementAndGet();
if (capacity.get() == 0) { //signal all the manipulators to wake up and stop waiting for downloaded images.
downloaderNotFull.signalAll();
}
downloaderReentrantLock.unlock();
if (imageBean.getOriginalImage() != null) { // the downloader will set it null iff it failes to download it.
// business logic
}
manipulatedImagesBlockingQueue.add(imageBean);
signalAllPersisters(); // signal the persisters (which has the same lock/unlock as this manipulator.
} else {
try {
downloaderNotFull.await(); //manipulator will wait for downloaded image - downloader will signalAllManipulators (same as signalAllPersisters() here) when an imageBean will be inserted to queue.
downloaderReentrantLock.unlock();
} catch (InterruptedException e) {
logger.log(Level.ERROR, e.getMessage(), e);
}
}
}
}
logger.log(Level.INFO, "Manipulator: " + Thread.currentThread().getId() + " Ended Gracefully");
}
private void signalAllPersisters() {
manipulatorReentrantLock.lock();
manipulatorNotFull.signalAll();
manipulatorReentrantLock.unlock();
}
For full flow you can check this project on my github: https://github.com/roy-key/image-service/
Your issue is that you are trying to use a counter to track queue elements and aren't composing operations that need to be atomic. You are doing check, take, decrement. This allows the queue size and counter to desynchronize and your threads block forever. It would be better to write a synchronization primitive that is 'closeable' so that you don't have to keep an associated counter. However, a quick fix would be to change it so you are get and decrementing the counter atomically:
while (capacity.getAndDecrement() > 0) {
try {
ImageBean imageBean = downloadedImagesBlockingQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
In this case if there are 3 threads and only one element left in the queue then only one thread will atomically decrement the counter and see that it can take without blocking. Both other threads will see 0 or <0 and break out of the loop.
You also need to make all of your class instance variables final so that they have the correct memory visibility. You should also determine how you are going to handle interrupts rather than relying on the default print trace template.

How to return Value from Multi Threading? [duplicate]

This question already has answers here:
Returning value from Thread
(9 answers)
How can a Thread return a value after finishing its job?
(4 answers)
Closed 4 years ago.
My problem is, i just want to return value from Multi threading out of 4 threads running concurrently in Multiple times. I need a return value for every times thread calls and run. Please justify me thank you, My code snippet looking like this, Thread1: i was calling java to native library function, function returns integer value.
public void run() {
double time = System.currentTimeMillis();
println("Thread-1 starts " + time);
ED emot = new ED();
emot.edetect("str");
try {
Thread.sleep(1);
} catch {
}
println("Value: " + emot.getvalue);
i = emot.getvalue;
}
As far as I got your problem you have 4 threads which return some value after computation. Here are few ideas:
If your thread returns some result use Callable<V> else Runnable.
You can use ExecutorService to submit your task (thread) and will get Future<V> or Future<?> depending on whether it is Callable or Runnable.
If you want to receive result of all the threads you can submit all and get futures and then invoke future.get which blocks until result is received. If you want to receive result from any of the threads then in that case you can also use ExecutorCompletionService as well which maintains a queue of results in whatever order they are received.
In multi threaded environment, we can return the values from thread by using Executer Service. This feature is available from JDK 5.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html
Example :
public class MyThread implements Callable{
#Override
public String call(){
Thread.sleep(2000);
return "Hello";
}
public static void main(String args[]){
ExecutorService executor = Executors.newFixedThreadPool(5);
Callable<String> callable = new MyThread();
String value = executor.submit(callable);
System.out.println("The returned value is : "+value);
executor.shutdown();
}
}
This is the way you can return the values from thread.
You could make that object, emot, a class variable. This way, when you make the new object in your main thread, you could access that value through a getter method.
public static void main(String[] args) {
//Your code
YourRunnableClass r = new YourRunnableClass();
Thread yourThread = r;
yourThread.start();
//other code
r.getValue() //The value you are trying to get
}
public class YourRunnableClass implements Runnable {
private ED emot;
public int getValue() {
return emot.getvalue();
}
public void run() {
//Your Code
}
}

Thread Synchronization - Synchronizing three threads to print 012012012012..... not working

I am trying to synchronize three threads to print 012012012012.... but it is not working correctly. Each thread is assigned a number which it prints when it receives a signal from main thread. There is something wrong with the following program which I am not able to catch.
public class Application {
public static void main(String[] args) {
int totalThreads = 3;
Thread[] threads = new Thread[totalThreads];
for (int i = 0; i < threads.length; i++) {
threads[i] = new MyThread(i);
threads[i].start();
}
int threadIndex = 0;
while (true) {
synchronized(threads[threadIndex]) {
threads[threadIndex].notify();
}
threadIndex++;
if (threadIndex == totalThreads) {
threadIndex = 0;
}
}
}
}
class MyThread extends Thread {
private int i;
public MyThread(int i) {
this.i = i;
}
#Override
public void run() {
while (true) {
synchronized(this) {
waitForSignal();
System.out.println(i);
}
}
}
private void waitForSignal() {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You need more coordination. the notify call does not immediately wake up the thread and force it to proceed. Instead, think of notify as sending an email to the thread to let it know that it can proceed. Imagine if you wanted your 3 friends to call you in order. You sent friend 1 an email to call you, waited one second, sent an email to friend 2, waited a second, and sent an email to friend 3. do you think you'd get called in that exact order?
one way to add more coordination would be to have some shared state which indicates whose turn it is. if all your friends could see your house, you could put a number on the outside of the house indicating whose turn it was to call. each friend would wait until they saw their number, and then call.
Here's your problem:
int threadIndex = 0;
while (true) {
synchronized(threads[threadIndex]) {
threads[threadIndex].notify();
}
threadIndex++;
if (threadIndex == totalThreads) {
threadIndex = 0;
}
}
The main thread notifies all threads in the right order. However, your threads are working independently. They may or may not get scheduled at a specific point in time. So the end result may be, that thread 2 is reaching the wait/print lock before thread 1 before thread 0. The final order is not determined by you sending the notifications, but (in essence) by the scheduler.
The solution is to change it this way:
the main thread notifies exactly one thread: thread 0
every thread does his work and when done, notifies the next thread in line
obviously the last thread has to notify thread 0 again.
Another possible solution: In the main thread, you can wait immediately after having notified a thread (in the same synchronized block), like this:
synchronized (threads[threadIndex])
{
threads[threadIndex].notify();
threads[threadIndex].wait(); // try/catch here
}
And in the run method of the thread, you can use notifyAll to wake up the main thread after the thread finished its work:
synchronized (this)
{
waitForSignal();
System.out.println(i);
notifyAll();
}
More sophisticated solutions would involve classes from the java.util.concurrent.locks package.
package threads;
import java.util.concurrent.Semaphore;
public class ZeroEvenOddPrinter {
class Runner extends Thread{
Semaphore prev;
Semaphore next;
int num = 0;
public Runner(Semaphore prev,Semaphore next,int num){
this.prev = prev;
this.next = next;
this.num = num;
}
#Override
public void run(){
while (true) {
try {
Thread.sleep(100);
prev.acquire();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (num == 0)
System.out.println(0);
else {
System.out.println(num);
num = num + 2;
}
next.release();
}
}
}
static public void main(String args[]) throws InterruptedException{
Semaphore sem1 = new Semaphore(1);
Semaphore sem2 = new Semaphore(1);
Semaphore sem3 = new Semaphore(1);
ZeroEvenOddPrinter zeo = new ZeroEvenOddPrinter();
Runner t1 = zeo.new Runner(sem1,sem2,0);
Runner t2 = zeo.new Runner(sem2,sem3,1);
Runner t3 = zeo.new Runner(sem3,sem1,2);
sem1.acquire();
sem2.acquire();
sem3.acquire();
t1.start();
t2.start();
t3.start();
sem1.release();
}
}
Here i am using semaphores as triggers for all the three threads. Initially all threads will be blocked on sem1,sem2,sem3. Then i will release the sem1 and first thread will execute then it will release the second thread and so on... The best part is you extend this logic to n number of threads. Good Luck!!!

Is there a way to declare a method as a new Thread in Java

I have a program which is listening for random numbers. It is hooked up to a publisher which gives me a number and a new count and every time I get an update, I'm storing the current count for that number in a HashMap.
I also have an SSL server listening for requests. When a request comes in asking "how many 7's do we have" I just return the value in my HashMap.
Now I want to add logic that says, if we have 0 occurrences of that number, wait until we get one, and return the count at that point. However I'm struggling because of the limitation on the Thread's run method, that it must be a void. I wonder if there is anyway to just declare my method as one that always launches a new thread, or maybe a better way to handle it than what I am doing. Here is what I have:
private static volatile HashMap<Integer, Integer> occurenceMap= new HashMap<Integer, Integer>();
public synchronized static int getNumOccurrences(final Integer number) {
try {
(new Thread() {
public void run() {
Integer occurrences = occurenceMap.get(number);
if ( occurrences != null && occurrences > 0 ) {
// here I would like to just return occurences;
} else {
CountDownLatch latch = new CountDownLatch(1);
pendingList.put(number, latch);
latch.await();
// elsewhere in the code, I call countdown when I get a hit
pendingList.remove(number);
// once we've counted down, I would like to return the value
}
}
}).start();
} catch ( Throwable t ) { }
}
However, I can't put return statements in the run method. So how is this best done?
Thank you!
You'd need some kind of external structure to store the number, like this
// declared outside your runnable
final AtomicInteger result = new AtomicInteger(0);
// in your run method
// return value; // doesn't work, can't return
result.set(value);
So adding it into yours, you get this
Note that my comments start with // C:
private static volatile HashMap<Integer, Integer> occurenceMap= new HashMap<Integer, Integer>();
public synchronized static int getNumOccurrences(final Integer number) {
// C: here's a container to use inside the runnable
// C: must be final to use inside the runnable below
final AtomicInteger result = new AtomicInteger(0);
try {
// C: keep a rerefence to the thread we create
Thread thread = new Thread() {
public void run() {
Integer occurrences = occurenceMap.get(number);
if ( occurrences != null && occurrences > 0 ) {
result.set(occurences); // C: we found what we're looking for
return; // C: so get out of the run method
} else {
CountDownLatch latch = new CountDownLatch(1);
pendingList.put(number, latch);
latch.await();
// elsewhere in the code, I call countdown when I get a hit
pendingList.remove(number);
// once we've counted down, I would like to return the value
result.set(1); // C: I'm not sure what you want to return here
return; // C: but I'm sure you can figure that out...
}
}
});
thread.start(); // C: now start the thread
thread.join(); // C: join the thread, waiting for it to finish
} catch ( Throwable t ) { }
return result.get(); // C: now return the int from the container
}
Another way to result values from your Thread execution it is to use the Executors thread-pools which allow you to submit a Callable:
// create a thread pool with 10 workers
ExecutorService threadPool = Executors.newFixedThreadPool(10);
List<Future<Integer>> futures = new ArrayList<Future<Integer>>();
for (Job job : jobsToDo) {
futures.add(threadPool.submit(new Callable<Integer>() {
public Integer call() {
...
}
}));
}
// after submitting the jobs, you need to shutdown the queue
threadPool.shutdown();
// then you can get the results
for (Future<Integer> future : futures) {
// this will throw if your call method throws
int value = future.get();
}

Categories

Resources