I am trying to simulate a triatlon competition using CyclicBarrier but it doesn't work as expected and I don't know why.
Each part of the competition has to wait till all the runners have completed the previous one, but it seems like it's waiting forever.
This is the piece of code for the phase one:
class Runner implements Runnable
{
private CyclicBarrier bar = null;
private static int runners;
private static double[] time;
private int number;
public static String name;
public Runner(int runners, String name)
{
time = new double[runners];
for (int i=0; i<runners; i++)
time[i] = 0;
this.name= name;
}
public Runner(CyclicBarrier bar, int number)
{
this.bar = bar;
this.number = number;
}
public void run()
{
try { int i = bar.await(); }
catch(InterruptedException e) {}
catch (BrokenBarrierException e) {}
double tIni = System.nanoTime();
try { Thread.sleep((int)(100*Math.random()); } catch(InterruptedException e) {}
double t = System.nanoTime() - tIni;
time[number] += t;
}
}
public class Triatlon
{
public static void main(String[] args)
{
int runners = 100;
CyclicBarrier Finish_Line_1 = new CyclicBarrier (runners);
Runner c = new Runner(runners, "Triatlon");
ExecutorService e = Executors.newFixedThreadPool(runners);
for (int i=0; i<runners; i++)
e.submit(new Runner(Finish_Line_1, i));
System.out.println(Finish_Line_1.getNumberWaiting()); // this always shows 99
try { int i = Finish_Line_1.await(); }
catch(InterruptedException e01) {}
catch (BrokenBarrierException e02) {}
System.out.println("Swimming phase completed");
// here the rest of the competition, which works the same way
}
}
You have an off-by-one error: you create a CyclicBarrier for 100 threads, but execute 101 awaits, the one-off being in the main method. Due to the semantics of the cyclic barrier, and subject to nondeterministic conditions, your main thread will be the last to execute await, thereby being left alone waiting for another 99 threads to join in.
After you fix this problem, you'll find out that the application keeps running even after all work is done. This is because you didn't call e.shutdown(), so all the threads in the pool stay alive after the main thread is done.
BTW getNumberWaiting always shows 0 for me, which is the expected value after the barrier has been lowered due to 100 submitted threads reaching it. This is nondeterministic, however, and could change at any time.
CyclicBarrier cycles around once all parties have called await and the barrier is opened. Hence the name.
So if you create it with 5 parties and there are 6 calls to await the last one will trigger it to be waiting again for 4 more parties to join.
That's basically what happens here as you have the 1 extra await call in your main. It is waiting for another runners-1 calls to happen.
The simple fix is to create the CyclicBarrier with runners+1 parties.
Related
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.
I have a problem in Java where I want to spawn multiple concurrent threads simultaneously. I want to use the result of whichever thread/task finishes first, and abandon/ignore the results of the other threads/tasks. I found a similar question for just cancelling slower threads but thought that this new question was different enough to warrant an entirely new question.
Note that I have included an answer below based what I considered to be the best answer from this similar question but changed it to best fit this new (albeit similar) problem. I wanted to share the knowledge and see if there is a better way of solving this problem, hence the question and self-answer below.
You can use ExecutorService.invokeAny. From its documentation:
Executes the given tasks, returning the result of one that has completed successfully …. Upon normal or exceptional return, tasks that have not completed are cancelled.
This answer is based off #lreeder's answer to the question "Java threads - close other threads when first thread completes".
Basically, the difference between my answer and his answer is that he closes the threads via a Semaphore and I just record the result of the fastest thread via an AtomicReference. Note that in my code, I do something a little weird. Namely, I use an instance of AtomicReference<Integer> instead of the simpler AtomicInteger. I do this so that I can compare and set the value to a null integer; I can't use null integers with AtomicInteger. This allows me to set any integer, not just a set of integers, excluding some sentinel value. Also, there are a few less important details like the use of an ExecutorService instead of explicit threads, and the changing of how Worker.completed is set, because previously it was possible that more than one thread could finish first.
public class ThreadController {
public static void main(String[] args) throws Exception {
new ThreadController().threadController();
}
public void threadController() throws Exception {
int numWorkers = 100;
List<Worker> workerList = new ArrayList<>(numWorkers);
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(1);
//Semaphore prevents only one thread from completing
//before they are counted
AtomicReference<Integer> firstInt = new AtomicReference<Integer>();
ExecutorService execSvc = Executors.newFixedThreadPool(numWorkers);
for (int i = 0; i < numWorkers; i++) {
Worker worker = new Worker(i, startSignal, doneSignal, firstInt);
execSvc.submit(worker);
workerList.add(worker);
}
//tell workers they can start
startSignal.countDown();
//wait for one thread to complete.
doneSignal.await();
//Look at all workers and find which one is done
for (int i = 0; i < numWorkers; i++) {
if (workerList.get(i).isCompleted()) {
System.out.printf("Thread %d finished first, firstInt=%d\n", i, firstInt.get());
}
}
}
}
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
// null when not yet set, not so for AtomicInteger
private final AtomicReference<Integer> singleResult;
private final int id;
private boolean completed = false;
public Worker(int id, CountDownLatch startSignal, CountDownLatch doneSignal, AtomicReference<Integer> singleResult) {
this.id = id;
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.singleResult = singleResult;
}
public boolean isCompleted() {
return completed;
}
#Override
public void run() {
try {
//block until controller counts down the latch
startSignal.await();
//simulate real work
Thread.sleep((long) (Math.random() * 1000));
//try to get the semaphore. Since there is only
//one permit, the first worker to finish gets it,
//and the rest will block.
boolean finishedFirst = singleResult.compareAndSet(null, id);
// only set this if the result was successfully set
if (finishedFirst) {
//Use a completed flag instead of Thread.isAlive because
//even though countDown is the last thing in the run method,
//the run method may not have before the time the
//controlling thread can check isAlive status
completed = true;
}
}
catch (InterruptedException e) {
//don't care about this
}
//tell controller we are finished, if already there, do nothing
doneSignal.countDown();
}
}
in this project I am trying to do some concurrency among threads using semaphores as signaling, however the concurrency is not working at all. I can only use acquire and release and no synchronized keyword methods allowed. I read countless webpages and it says that
// do something
acquire()
release()
//do something
Which I understand but in this program I am trying to test signals with a semaphore between threads, for example user requests deposit and teller should say deposit completed.However my signals(semaphores) are not working as I want to print in order for example
I need to deposit
Deposit is complete
instead I get this
Customer0created
I need to deposit
I have withdrawn <---
Customer0joined from main
Teller0created
You wanna withdrawal? <---- (out of order)
Deposit is complete
Regardless how i reorder them or how much i read the semaphore signaling to comm threads is not working.
[code]import java.util.concurrent.Semaphore;
public class Threads {
private static Semaphore depositTransaction = new Semaphore (1, true);
private static Semaphore withdrawal = new Semaphore (1, true);
public static void main(String[] args)
{
final int customerThreads = 1;
final int tellerThreads = 1;
final int loanThreads = 1;
Customer thr[] = new Customer[customerThreads]; //
Thread cThread[] = new Thread[customerThreads]; //
for (int i= 0; i < customerThreads; i++)
{
thr[i]= new Customer(i);
cThread[i] = new Thread(thr [i]);
cThread[i].start();
}
for ( int i = 0; i < customerThreads; i++ )
{
try {
cThread[i].join();
System.out.println("Customer"+i + "joined from main");
}
catch (InterruptedException e)
{
}
}
Teller thr1[] = new Teller[tellerThreads];
Thread tThread[] = new Thread[tellerThreads];
for (int b = 0; b< tellerThreads; b++)
{
thr1[b] = new Teller(B)/>;
tThread[b]= new Thread(thr1 [b]);
tThread[b].start();
}
}
static class Customer implements Runnable
{
private int customerNumber = 0;
private int balance = 0;
Customer(int cn)
{
this.customerNumber = cn;
balance = 1000;
System.out.println("Customer"+ customerNumber + "created");
}
public void run()
{
try
{
System.out.println("I need to deposit");
depositTransaction.acquire();// signal
}
catch(InterruptedException e)
{
Thread.currentThread().interrupt();
e.printStackTrace();
}
withdrawal.release();
System.out.println("I have withdrawn");
}
}
static class Teller implements Runnable
{
private int tellerNumber = 0;
Teller(int tn)
{
this.tellerNumber = tn;
System.out.println("Teller"+ tellerNumber +"created");
}
public void run()
{
try
{
System.out.println("You wanna withdrawal?");
withdrawal.acquire();
}
catch(InterruptedException e)
{
Thread.currentThread().interrupt();
}
depositTransaction.release();
System.out.println("Deposit is complete");
}
}
}[/code]
Here is a program that uses a semaphore to play ping pong. It is very similar to what you need for your goal. This program has one thread that will print PING, and the other prints PONG. It uses a semaphore to ensure that PING is printed first, then PONG, then PING and so on.
Notice how this program uses two semaphores, and that it starts both semaphores at zero. This means that when the threads call acquire() on it, they will block. You have been using the value of one, which means that neither thread would block and that both would rush ahead.
Now that all threads have blocked, we need to get one of them to start. We send a 'release()' signal to the semaphore that the thread that we want to start up on. That will increment the semaphore by one, and the thread blocked in acquire() will wake up and decrement it again before proceeding with its all important job of printing PING or PONG.
Remember the following about semaphores:
A semaphore contains an integer value (called a permit count)
acquire() will block until the integer value is greater than zero; when greater than zero the count will be decremented by one before exiting
release() never blocks. It only ever increments the integer value by one, and as a side effect wakes up any method that were blocked in a call to acquire().
Thus for a game of ping pong to work: (ascii art below scrolls to the right)
s1=0 -- release() --> s1=1 s1=0
s2=0 s2=0 s2=1
thread1=blocked thread1 runs -- calls s2.release() --> thread1 blocked
thread2=blocked thread2=blocked thread2 runs
Notice how the values of s1 and s2 oscilate between 0 and 1, but we do not allow them both to have the value of 1 at the same time. If they were ever to both equal 1, then both thread1 and thread2 would be able to run at the same time. Which would be known as a race condition, as the order of their execution would be unpredictable.
public class PingPong {
public static void main( String[] args ) throws InterruptedException {
final Semaphore s1 = new Semaphore(0);
final Semaphore s2 = new Semaphore(0);
final AtomicInteger countDown = new AtomicInteger( 10 );
Thread threadA = new Thread() {
public void run() {
try {
System.out.println("threadA started");
while (countDown.get() > 0) {
s1.acquire();
System.out.println( "PING" );
s2.release();
countDown.decrementAndGet();
}
} catch ( InterruptedException e ) {
e.printStackTrace();
}
System.out.println("threadA finished");
}
};
Thread threadB = new Thread() {
public void run() {
try {
System.out.println("threadB started");
while (countDown.get() > 0) {
s2.acquire();
System.out.println( "PONG" );
s1.release();
countDown.decrementAndGet();
}
} catch ( InterruptedException e ) {
e.printStackTrace();
}
System.out.println("threadb finished");
}
};
threadA.start();
threadB.start();
s1.release();
}
}
You are not using semaphores correctly for what you want to do. As I get it, you want to start the customer thread, then block until the teller threads finishes then finish the customer thread.
Right now your semaphore do close to nothing. They will prevent multiple customer threads from running at the same time, but within your acquire / release block, nothing happens.
If you want to synchronize between customer and teller, both classes need to use the same Semaphore
What I would suggest is this :
remove the join operation for now
create the depositTransaction semaphore with count 0, so the first acquire will block.
Start a customer thread
The thread will block waiting for a deposit
Start a teller thread
make the deposit and release the depositTransaction semaphore
the customer thread will unblock
you can now join both threads
Edit :
I don't think that your idea of adding tons of semaphore for every action is a good idea. You will end up with complex locking and deadlocks all over the place. What I would suggest is to limit the number of semaphore and implement messages between the threads. The semaphore will tell the other one (Client tells Teller and vice-versa) to check the messages after pushing one.
Start customer thread
push message that customer is waiting
signal for new customer request
wait for teller signal
Start teller thread
acquire sem for new customer request
check message
do stuff
signal customer that stuff is done
messages will then be "withdrawal customer 0" or any other action you want to implement
Would suggest you to look at one of the standard examples and rework your code. Semaphore is very easy to use and all we need to do is acquire the lock when a thread accesses the shared resource and release the lock when it it is done.
There is nice example with a producer and a consumer thread protecting a shared resource here.
Semaphore Example with a Producer and Consumer thread
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!!!
I have kind of confused about the "Semaphore" class in java.util.concurrent package. Here are my code snippet:
import java.util.concurrent.Semaphore;
public class TestSemaphore {
public static void main(String[] args){
Semaphore limit = new Semaphore(2);
SemaphoreAA s = new SemaphoreAA(limit);
AAThread a = new AAThread(s);
Thread[] sThread = new Thread[100];
for(int i = 0; i<100; i++){
sThread[i] = new Thread(a,"[sThread"+i+"]");
sThread[i].start();
}
}
}
class SemaphoreAA{
private static int counter;
private Semaphore limit;
public SemaphoreAA(Semaphore limit){
this.limit = limit;
}
public void increment() throws InterruptedException{
System.out.printf("%-15s%-25s%5d%n",Thread.currentThread().getName()," : Before Increment. Current counter: ",counter);
limit.acquire();
System.out.printf("%-15s%-25s%n",Thread.currentThread().getName()," : Get the resource. Start to increment.");
counter++;
System.out.printf("%-20s%-40s%5d%n",Thread.currentThread().getName()," : Increment is done. Current counter: ",counter );
limit.release();
}
}
class AAThread implements Runnable{
private SemaphoreAA s;
public AAThread(SemaphoreAA s){
this.s = s;
}
public void run() {
try {
s.increment();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I understand it can be used to control accesses to resources. And if I set the limit to one, like this "Semaphore limit = new Semaphore(1);", it seems like a lock. It was proved. If I set the limit to two, I expect there are two threads in the given time to access to the increment() method and it might cause data race. The output might be like this:
[sThread3] : Before Increment. Current counter: 2
[sThread4] : Before Increment. Current counter: 2
[sThread3] : Get the resource. Start to increment.
[sThread4] : Get the resource. Start to increment.
[sThread3] : Increment is done. Current counter: 3
[sThread4] : Increment is done. Current counter: 3
However, though I had tried several times, the result expected didn't occur. So I wanna know if I misunderstood it. Thanks.
You understood it right.
However, though I had tried several times, the result expected didn't occur.
Just because it can appear doesn't mean it will. This is the problem with most concurrency bugs: they sometimes appear, sometimes not.
If you want to increase the likelihood of an error you can increase the number of Threads or create/start them in two different loops after each other.