Java - implementation of the mechanism for waiting for employment

in my project, I still have several threads "synchronized" (each of them works with one Runnable type) using CyclicBarrier . In my case, using CyclicBarrier turned out to be ineffective due to the high synchronization frequency, but the busy-waiting mechanism could work faster. Here is what I got so far (some parts have been omitted):

 public class MyRunnable implements Runnable { private static AtomicInteger counter = null; // initialized to the number // of threads public void run() { // do work up to a "common point" synchronized (this) { // decrement the counter and - if necessary - reset it if (counter.decrementAndGet() == 0) { counter.set(numberOfThreads); // make all the busy waiting threads exit from the loop for (int i = 0; i < threads.length; i++) threads[i].interrupt(); } } // busy wait until all threads have reached the "common point" while (!Thread.interrupted()) {} } } 

Unfortunately, this code performs even worse than CyclicBarrier . The following is a short, compiled example. Any suggestions for improving it?

+3
source share
4 answers

Waiting for employment here will only work β€œfaster”, if you have more processors, then you have threads. If you constantly turn to Thread.interrupted and just consume CPU time, you will significantly degrade performance.

What went wrong with CyclicBarrier / CountDownLatch? This seems like a much better solution.

+3
source

How about something like that? This code has a concurrency error (if one thread is slower between calls to counter.get() ), but it must be resolved using two counters and repeating this code twice so that the counters alternate.

 if (counter.decrementAndGet() == 0) { counter.set(numberOfThreads); } else { while (counter.get() < numberOfThreads) {} } 

Please send an example that can be compiled and which demonstrates a performance problem. Otherwise, all answers will be just assumptions.

+1
source

It is hard to imagine that a busy-wait loop would be faster than not busy. First of all, in your code you still use at least the synchronization that you will need when using CyclicBarrier (see below). Secondly, you have just implemented the CyclicBarrier mechanism, in which Java developers spend time and energy optimizing for maximum performance. Thirdly, CyclicBarrier uses ReentrantLock for synchronization, which seems to be more efficient and faster than using the synchronized . Therefore, in general, it is unlikely that your code will win the race.

Consider this reference code:

 public class MyRunnable implements Runnable { private static CyclicBarrier barrier = new CyclicBarrier(threads.length); public void run() { // do work up to a "common point" try{ barrier.await(); }catch(InterruptedException e){ Thread.interrupt(); //Something unlikely has happened. You might want to handle this. } } } 

In one run, this code will synchronize thread.length times, which is no more than in your version with the expected expectation. Therefore, it cannot be slower than your code.

The real cause of the performance problem is that your threads do not work much before they β€œmeet”, which probably means that the overhead is with a high context flow and also a lot of synchronization.

Can you redefine architecture? Do you really need to wait for all employees to β€œmeet” at a common point? Can you do a little more work before they "meet"? Have you tried setting the number of threads to a smaller number (= CPU / core count)?

Can you tell a little more about the purpose of the code and give a little more detailed information?

+1
source

How about pending / notification?

 public class MyRunnable implements Runnable { private static AtomicInteger counter = null; // initialized to the number // of threads public void run() { // do work up to a "common point" // need to synchronize for wait/notify. synchronized ( counter ) { // decrement the counter and - if necessary - reset it if (counter.decrementAndGet() == 0) { counter.set(numberOfThreads); // notify all the waiting threads counter.notifyAll(); }else{ // wait until all threads have reached the "common point" counter.wait(); } } } } 

In the general case, if you synchronize so often that problems with the barrier are a problem, it is suspicious: either you are doing work that is not worth the multithreading, or you are synchronizing more often than it should be.

0
source

All Articles