Why does my multithreaded code leads to hang? - java

I study java concurency.
I am trying to estimate time execution depends on thread count(read and write)
my code:
public class Task5 {
public static int [] readerThreadCount = {1,10,100,1000};
public static int [] writerThreadCount = {10, 1000, 1000000};
public static void main(String[] args) throws InterruptedException {
for (int readCount : readerThreadCount) {
for (int writeCount : writerThreadCount) {
System.out.println(readCount + "/" + writeCount + " = " + test(readCount, writeCount, new ArrayHolderBySynchronized()));
}
}
}
private static long test(int readCount, int writeCount, ArrayHolder arrayHolder) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(readCount + writeCount);
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < readCount; i++) {
threads.add(new Thread(new ArrayReader(arrayHolder, countDownLatch)));
}
for (int i = 0; i < writeCount; i++) {
threads.add(new Thread(new ArrayWriter(arrayHolder, countDownLatch)));
}
for(Thread thread:threads){
thread.start();
}
countDownLatch.await();//all threads started
long start = System.currentTimeMillis();
for (Thread thread : threads) {
thread.join();
}
return System.currentTimeMillis() - start;
}
}
class ArrayHolderBySynchronized extends ArrayHolder {
#Override
public synchronized int get(int index) {
return arr[index];
}
#Override
public synchronized void write(int index, int value) {
arr[index] = value;
}
}
class ArrayReader implements Runnable {
ArrayHolder arrayHolder;
CountDownLatch countDownLatch;
ArrayReader(ArrayHolder arrayHolder, CountDownLatch countDownLatch) {
this.arrayHolder = arrayHolder;
this.countDownLatch = countDownLatch;
}
#Override
public void run() {
countDownLatch.countDown();
arrayHolder.get(new Random().nextInt(ArrayHolder.ARRAY_SIZE));
}
}
class ArrayWriter implements Runnable {
ArrayHolder arrayHolder;
CountDownLatch countDownLatch;
ArrayWriter(ArrayHolder arrayHolder, CountDownLatch countDownLatch) {
this.arrayHolder = arrayHolder;
this.countDownLatch = countDownLatch;
}
#Override
public void run() {
countDownLatch.countDown();
arrayHolder.write(new Random().nextInt(ArrayHolder.ARRAY_SIZE), -1);
}
}
abstract class ArrayHolder {
public static int ARRAY_SIZE = 1_000_000;
protected int[] arr = generateArray();
private int[] generateArray() {
int[] arr = new int[ARRAY_SIZE];
for (int i = 0; i < ARRAY_SIZE; i++) {
arr[i] = i + 1;
}
return arr;
}
public abstract int get(int index);
public abstract void write(int index, int value);
}
it outputs
1/10 = 0
1/1000 = 1
and hangs.
I have not ideas why.
please help.

It doesn't hang, starting 1000000 threads just takes 1000 times longer than starting 1000 threads (a couple minutes, on my machine):
> java Task5
1/10 = 0
1/1000 = 1
1/1000000 = 63
10/10 = 0
10/1000 = 0
10/1000000 = 60
100/10 = 0
100/1000 = 0
100/1000000 = 63
1000/10 = 0
1000/1000 = 0
1000/1000000 = 60
Your next question will likely be why your test reports a duration of 60 ms when it took minutes to execute. That's because starting a threads is far more expensive than counting down a latch, or reading from or writing to a single array element, and you only measure the latter.

Related

how to use agrona.OneToOneRingBuffer

I just want to test agrona.OneToOneRingBuffer. i have one Producer to produce message,one Consumer to consume.But My consumer class has no output because countdownlatch doesn't zero out.
public class Producer implements Runnable{
private final RingBuffer buffer;
public Producer(RingBuffer buffer) {
this.buffer = buffer;
}
#Override
public void run() {
for(int i=0;i<Config.SIZE;i++){
String s = String.format("i am %s",i);
System.out.println( "name -> " + s);
UnsafeBuffer unsafeBuffer = new UnsafeBuffer(s.getBytes());
unsafeBuffer.wrap(s.getBytes());
buffer.write(1, unsafeBuffer, 0, s.length());
}
}
}
public class Consumer implements Runnable {
private final RingBuffer buffer;
public Consumer(RingBuffer buffer) {
this.buffer = buffer;
}
#Override
public void run() {
long start = System.currentTimeMillis();
CountDownLatch countDownLatch = new CountDownLatch(Config.SIZE);
while (countDownLatch.getCount() > 0) {
buffer.read((msgTypeId, srcBuffer, index, length) -> {
byte[] message = new byte[length];
srcBuffer.getBytes(index, message);
System.out.println("Consumer <- " + new String(message));
countDownLatch.countDown();
});
}
long end = System.currentTimeMillis();
System.out.println("cost time " + (end - start));
}
}
public class App {
private static final OneToOneRingBuffer BUFFER = new OneToOneRingBuffer(new UnsafeBuffer(
ByteBuffer.allocate(1024 + RingBufferDescriptor.TRAILER_LENGTH)));
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(new Producer(BUFFER));
executor.execute(new Consumer(BUFFER));
Thread.currentThread().join();
}
}
The Config.SIZE just set to 100_000 and when it was 10_000 ,the programe runs well.
Is the OneToOneRingBuffer class a thread-unsafe class?

simple barrier synchronisation in java

im trying to understand the barrier problem. im still really new to programming but was presented with this problem in class to solve.
"I have to solve the barrier problem using counting semaphores. You can assume that there is a shared variable N which indicates the number of concurrent threads in the system. When the first N −1 threads arrive at the barrier, they should block until the Nth thread arrives, at which point all threads might proceed.
The shared counter variable can be used to keep track of the number of threads that have arrived and the semaphores mutex and barrier can be used to solve the synchronization problem."
import java.util.concurrent.Semaphore;
public class BarrierSynchronization extends Thread {
int N;
int count;
Semaphore mutex;
Semaphore barrier;
public BarrierSynchronization ()
{
this.N = 5;
this.count = 0;
this.mutex = new Semaphore(1);
this.barrier = new Semaphore(0);
}
public void run()
{
try {
mutex.acquire();
count = count + 1;
System.out.println(Thread.currentThread().getName() + ": " + count);
mutex.release();
if (count == N)
{
barrier.release();
System.out.println("All " + count + " threads have reached the barrier. The barrier is now open" );
} // unblock one thread
barrier.acquire();
barrier.release();
System.out.println(Thread.currentThread().getName() + " has passed the barrier");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
i tried to implement the pseudo code from the little book of semaphores. i called on this thread in main class and ran it but it gives an error about mutex.wait() for some reason. when i remove that bit of the code it runs but shows nothing. what exactly am i supposed to do for this problem?
public class Main {
public static void main(String[] args) throws InterruptedException
{
BarrierSynchronization barrier = new BarrierSynchronization();
Thread bs1 = new Thread(barrier);
Thread bs2 = new Thread(barrier);
Thread bs3 = new Thread(barrier);
Thread bs4 = new Thread(barrier);
Thread bs5 = new Thread(barrier);
bs1.start();
bs2.start();
bs3.start();
bs4.start();
bs5.start();
}
why does it output the rare one before the barrier is unlocked for all the threads? i think im close enough to solving this problem. is a race condition or something?
CLICK TO SEE IMAGE
Might be a bit late, but here is an implementation with a driver code that works. You have to garante mutual exclusion and keep track of the number of threads that arrive at the barrier.
public class Barrier {
private int capacity;
private Semaphore s, exclusao, counter;
public Barrier(int capacity) {
this.capacity = capacity;
counter = new Semaphore(0);
s = new Semaphore(0);
exclusao = new Semaphore(1);
}
public void espera() throws InterruptedException {
exclusao.acquire();
if (counter.availablePermits() < capacity - 1) {
counter.release();
exclusao.release();
s.acquire();
} else {
exclusao.release();
System.out.println("RELEASE ALL");
for (int i = 0; i < capacity; i++) {
s.release();
}
}
}
}
class TesteThread extends Thread {
private Barrier b;
private long waitPeriod;
public TesteThread(long wait, Barrier b) {
this.b = b;
this.waitPeriod = wait;
System.out.println("Thread started" + this.getName());
}
public void espera() throws InterruptedException {
b.espera();
}
#Override
public void run() {
try {
System.out.println("Thread a dormir " + this.getName());
sleep(waitPeriod);
System.out.println("Thread a esperar " + this.getName());
espera();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class BarrierExample {
public static void main(String[] args) throws InterruptedException {
Barrier BR = new Barrier(5);
TesteThread[] teste = new TesteThread[5];
for (int i = 0; i < teste.length; i++) {
teste[i] = new TesteThread((long) (Math.random() * 1000), BR);
teste[i].start();
}
for (int i = 0; i < teste.length; i++) {
teste[i].join();
}
}
}`package examesFSO.exame2020_normal;
import java.util.concurrent.Semaphore;
public class Barrier {
private int capacity;
private Semaphore s, exclusao, counter;
public Barrier(int capacity) {
this.capacity = capacity;
counter = new Semaphore(0);
s = new Semaphore(0);
exclusao = new Semaphore(1);
}
public void espera() throws InterruptedException {
exclusao.acquire();
if (counter.availablePermits() < capacity - 1) {
counter.release();
exclusao.release();
s.acquire();
} else {
System.out.println("RELEASE ALL");
for (int i = 0; i < capacity; i++) {
s.release();
}
}
exclusao.release();
}
}
class TesteThread extends Thread {
private Barrier b;
private long waitPeriod;
public TesteThread(long wait, Barrier b) {
this.b = b;
this.waitPeriod = wait;
System.out.println("Thread instanciada " + this.getName());
}
public void espera() throws InterruptedException {
b.espera();
}
#Override
public void run() {
try {
System.out.println("Thread a dormir " + this.getName());
sleep(waitPeriod);
System.out.println("Thread a esperar " + this.getName());
espera();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class BarrierExample {
public static void main(String[] args) throws InterruptedException {
Barrier BR = new Barrier(5);
TesteThread[] teste = new TesteThread[5];
for (int i = 0; i < teste.length; i++) {
teste[i] = new TesteThread((long) (Math.random() * 1000), BR);
teste[i].start();
}
for (int i = 0; i < teste.length; i++) {
teste[i].join();
}
}
}

Is there any alternate way to enable Multithreading without using Join in my below code

Currently I am using join() to join my current thread. As far as i know join will make it plain sequential code. I want to do it in multithreading.
public class A {
private static final Logger logger = LoggerFactory.getLogger(A.class);
#Value("${query.interval}")
private String queryInterval;
private Set<B> missingKeys = new HashSet<>();
private Map<E, String> erroredKeys;
public Map<B, Collection<Product>> methodA(
List<B> searchKeyList) {
long startTime = System.currentTimeMillis();
missingKeys = new HashSet<>();
erroredKeys = new HashMap<>();
int size = searchKeyList.size();
int threadNumber = 0;
int startIndex = 0;
int endIndex = 0;
List<C> c = new ArrayList<>();
int qrySize = Integer.parseInt(queryInterval);
logger.info("Size of searchKeyList [{}] of instrument look up", new Object[] { searchKeyList.size() });
for (; threadNumber < size / rdsQrySize; threadNumber++) {
startIndex = threadNumber * rdsQrySize;
endIndex = startIndex + rdsQrySize;
logger.debug("Creating thread for Instrument LookUp");
c = createThread(threadNumber, startIndex, endIndex,
searchKeyList, c);
}
if (size % rdsQrySize != 0) {
startIndex = threadNumber * rdsQrySize;
endIndex = startIndex + size % rdsQrySize;
logger.debug("Creating EXTRA thread for Instrument LookUp");
c = createThread(requestor, businessLine, resolutionEnum, threadNumber, startIndex, endIndex,
searchKeyList, c);
}
// Here I don't want to use join. I am looking for any other way to do this
// to make my code run in multithreaded way
for (C lookUpThread : c) {
try {
lookUpThread.join();
} catch (InterruptedException e) {
}
}
Map<B, Collection<Product>> responseDataList = new HashMap<>();
for (C lookUpThread : c) {
Map<B, Collection<Product>> instrumentResponseData = lookUpThread.getInstrumentResponse()
.getFoundData();
missingKeys.addAll(lookUpThread.getInstrumentResponse().getMissingKeys());
erroredKeys.putAll(lookUpThread.getInstrumentResponse().getErroredKeys());
responseDataList.putAll(instrumentResponseData);
}
long stopTime = System.currentTimeMillis();
logger.info(
"[{}] milliseconds taken to fetch [{}] instruments from RDS divided in [{}] threads ",
new Object[] { stopTime - startTime,size, c.size() });
return responseDataList;
}
private List<C> createThread(int threadNumber, int startIndex, int endIndex,
List<B> searchKeyList, List<C> c) {
List<B> searchKeys = new ArrayList<>();
for (; startIndex < endIndex; startIndex++) {
searchKeys.add(searchKeyList.get(startIndex));
}
ProductRequest<B> request = new ProductRequest<>(
searchKeys);
logger.info("Creating thread no [{}] for Instrument LookUp", new Object[]{threadNumber});
C lookUpThread = new C("RDS Instrument Thread - " + threadNumber);
lookUpThread.setRequest(request);
lookUpThread.start();
c.add(lookUpThread);
return c;
}
public Set<B> getMissingKeys() {
return missingKeys;
}
public void setMissingKeys(Set<B> missingKeys) {
this.missingKeys = missingKeys;
}
public Map<E, String> getErroredKeys() {
return erroredKeys;
}
public void setErroredKeys(Map<E, String> erroredKeys) {
this.erroredKeys = erroredKeys;
}
// Inner class for thread
private class C extends Thread {
ClientResponse<B, Product, E> instrumentResponse = null;
ProductRequest<B> request = null;
C(String name) {
super.setName(name);
}
public void run() {
long startTime = System.currentTimeMillis();
instrumentResponse = rdsDao.getByKey(request);
long stopTime = System.currentTimeMillis();
logger.info("RDS responded in [{}] milliseconds for thread [{}] while Instrument Lookup",
new Object[] { stopTime - startTime, super.getName() });
}
public void setInstrumentResponse(
ClientResponse<B, Product, E> instrumentResponse) {
this.instrumentResponse = instrumentResponse;
}
public ClientResponse<B, Product, E> getInstrumentResponse() {
return instrumentResponse;
}
public void setRequest(ProductRequest<B> request) {
this.request = request;
}
public ProductRequest<B> getRequest() {
return request;
}
}
}
Your code is running concurrently (not sequentially as you mentioned).
ThreadT.join() will make the current thread to wait for the ThreadT to finish.
As you are spawning multiple threads, and joining with the Main thread, those non Main threads will still run concurrently (as you are calling Thread.start() in createThread()).
If you are not joining the non Main threads as above, then your Main thread/method will complete before those other non Main threads complete, which I guess is not desirable for you.

Deadlock in Producer - consumer thread

I have a problem with possible deadlock in "producer - consumer task".
Everything should be working in following way:
Producer should generate and add int[] arrays to collection
Consumer should take those arrays, put them to second collection and print in output
In debbug mode I have noticed that after a while both taks are suspended on this.wait(); method.
Could you help me and explain what is wrong with this code? :)
Thanks!
Producer task class
public class ProducerTask extends Thread{
private static final Object bufforLock = new Object();
private static LinkedList<Integer[]> buffor;
public ProducerTask(){
if(buffor == null)
buffor = new LinkedList<>();
this.setName("#ProducerTask");
}
#Override
public void run() {
synchronized (this) {
try {
for (int i = 0; i < 100; i++) {
while (isBufforFull()) {
System.err.println("ProducerTask is waiting");
this.wait();
}
Integer[] randomIntArray = getRandomIntArray();
addToBuffor(randomIntArray);
}
}
catch (InterruptedException ex) {
}
}
}
public static void removeLast(){
synchronized(bufforLock){
buffor.removeLast();
bufforLock.notifyAll();
}
}
public static Integer[] getLast(){
synchronized(bufforLock){
return buffor.getLast();
}
}
public static boolean isBufforFull(){
synchronized(bufforLock){
return buffor.size() == 10;
}
}
public static boolean isBufforEmpty(){
synchronized(bufforLock){
return buffor.isEmpty();
}
}
public static void addToBuffor(Integer[] array){
synchronized(bufforLock){
buffor.addFirst(array);
bufforLock.notifyAll();
}
}
public static LinkedList<Integer[]> getBuffor(){
synchronized(bufforLock){
return buffor;
}
}
private Integer[] getRandomIntArray(){
int maxSize = 10;
Integer[] array = new Integer[maxSize];
for(int i = 0 ; i < maxSize ; i++){
int value = (int) (Math.random() * 100);
array[i] = Integer.valueOf(value);
}
return array;
}
}
Consumer task class
public class ConsumerTask extends Thread {
private static LinkedList<Integer[]> buffor;
public ConsumerTask() {
if (buffor == null) {
buffor = new LinkedList<>();
}
this.setName("#ConsumerTask");
}
#Override
public void run() {
synchronized (this) {
try {
while (true) {
while (ProducerTask.isBufforEmpty()) {
System.err.println("ConsumerTask is waiting");
this.wait();
}
Integer[] array = ProducerTask.getLast();
this.arraySortByInserting(array);
this.buffor.addFirst(array);
ProducerTask.removeLast();
}
}
catch (InterruptedException ex) {}
}
}
private Integer[] arraySortByInserting(Integer[] aArrayToSort) {
if(aArrayToSort == null || aArrayToSort.length == 0)
return null;
this.printArray(aArrayToSort, "Array before sorting");
for (int i = 1; i < aArrayToSort.length; i++) {
int intValue = aArrayToSort[i];
int j = i;
while ((j > 0) && (aArrayToSort[j - 1] > intValue)) {
aArrayToSort[j] = aArrayToSort[j - 1];
j--;
}
aArrayToSort[j] = intValue;
}
this.printArray(aArrayToSort, "Array after sorting");
return aArrayToSort;
}
private void printArray(Integer[] aArray, String aMessage) {
System.out.print(aMessage + " [");
for (int intElement : aArray) {
System.out.print(intElement + " ");
}
System.out.print("]");
System.out.println();
}
}
You need a common object which would be used for inter thread communication.
Right now you are using this as object on which you get lock on and you notify on bufferLock in producer thread and same applies for consumer thread.
Remember both are two different instances and both successfully obtain lock on individual objects and then both enters wait state.

Java threads notify() wait() for faster calculation

I must create simple application with threads. Task: faster calculation than serial processing. I must use methods notify() or notifyAll(), wait(), interrupt() and operator synchronized.
I tried solve this by example from book. This example is typical producent consumer task. But parallel threads calculating is slower then serial.
Class with notify(), wait() and synchronized:
public class Reader {
private boolean isRead = false;
private boolean isFileEnd = false;
private int value;
private int[] pole;
private int pocitadlo=0;
public Reader(int[]pole) {
this.pole=pole;
}
synchronized public void loadValue() {
while (isRead == true) {
try {
wait();
}
catch (InterruptedException e) { }
}
if (pocitadlo<pole.length) {
value = pole[pocitadlo];
pocitadlo++;
}
else {
isFileEnd = true;
Thread.currentThread().interrupt();
}
isRead = true;
notifyAll();
}
synchronized public int getValue() {
while (isRead == false) {
try {
wait();
}
catch (InterruptedException e) { }
}
isRead = false;
if (isFileEnd == false) {
notifyAll();
return value;
}
else {
Thread.currentThread().interrupt();
return 0;
}
}
}
Producer class:
public class Producent extends Thread {
private Reader reader;
public Producent(Reader reader) {
this.reader = reader;
}
#Override
public void run() {
while (interrupted() == false) {
reader.loadValue();
}
}
}
Consumer class:
public class Konzument extends Thread {
private Reader reader;
private double sum = 0;
public Konzument(Reader reader) {
this.reader = reader;
}
#Override
public void run() {
int number;
while (true) {
number = reader.getValue();
if (interrupted() == false)
sum += Math.sqrt(number);
else
break;
}
}
public double getSum(){
return sum;
}
}
And main class code (I know that I can create objects in cycles for bigger comfort but this is only example):
public class PARPV2 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Watch watch=new Watch();
double suma=0;
int size=1000000;
int[]array1=new int[size];
int[]array2=new int[size];
int[]array3=new int[size];
int[]array4=new int[size];
int[]array5=new int[size];
generate(array1);
generate(array2);
generate(array3);
generate(array4);
generate(array5);
Reader reader1=new Reader(array1);
Reader reader2=new Reader(array2);
Reader reader3=new Reader(array3);
Reader reader4=new Reader(array4);
Reader reader5=new Reader(array5);
Producent p1=new Producent(reader1);
Konzument k1=new Konzument(reader1);
Producent p2=new Producent(reader2);
Konzument k2=new Konzument(reader2);
Producent p3=new Producent(reader3);
Konzument k3=new Konzument(reader3);
Producent p4=new Producent(reader4);
Konzument k4=new Konzument(reader4);
Producent p5=new Producent(reader5);
Konzument k5=new Konzument(reader5);
watch.start();
p1.start();
k1.start();
p2.start();
k2.start();
p3.start();
k3.start();
p4.start();
k4.start();
p5.start();
k5.start();
try {
p1.join();
k1.join();
p2.join();
k2.join();
p3.join();
k3.join();
p4.join();
k4.join();
p5.join();
k5.join();
suma=k1.getSum()+k2.getSum()+k3.getSum()+k4.getSum()+k5.getSum();
System.out.println("paralelne: "+watch.stop(false));
System.out.println("suma: "+suma);
} catch (InterruptedException ex) {
Logger.getLogger(PARPV2.class.getName()).log(Level.SEVERE, null, ex);
}
double sum1=0;
double sum2=0;
double sum3=0;
double sum4=0;
double sum5=0;
watch.start();
for (int i = 0; i < array1.length; i++) {
sum1+=Math.sqrt(array1[i]);
}
for (int i = 0; i < array2.length; i++) {
sum2+=Math.sqrt(array2[i]);
}
for (int i = 0; i < array3.length; i++) {
sum3+=Math.sqrt(array3[i]);
}
for (int i = 0; i < array4.length; i++) {
sum4+=Math.sqrt(array4[i]);
}
for (int i = 0; i < array5.length; i++) {
sum5+=Math.sqrt(array5[i]);
}
suma=sum1+sum2+sum3+sum4+sum5;
System.out.println("serial: "+watch.stop(false));
System.out.println("suma: "+suma);
}
public static void generate(int[]array){
Random r=new Random();
for (int i = 0; i < array.length; i++) {
array[i]=r.nextInt(100);
}
}
}
When I run this program, serial computing is much faster than parallel. But I have dual core and I thing that parallel calculation must be faster. I am not experienced in threads and maybe my example is dummy...Please, where can be a problem? Thanks
If you want faster execution using Threads, I think that you should use a single class that will accomplish the same thing as serial, something like that :
public class Calc extends Thread {
private int[] array;
private double sum;
public Calc(int[] array) {
this.array = array;
this.sum = 0;
}
#Override
public void run() {
for (int i = 0; i < array.length; i++) {
sum += Math.sqrt(array[i]);
}
}
public double getSum() {
return this.sum;
}
}
In this way, parallel computing is 2 times faster than serial coputing. I think the pattern Producer-Consummer you applied can't be faster than serial because you make way more instructions and breaks in the code by :
Getting a new value (Consumer waits a new item to be available)
Using this value (Producer waits consummer to finish its calculation)
Maybe the producer should be the one who generates random number, and the consummer the one using these values ?
(And please use while(isRead) and ! operator for the contrary instead of those ugly while(isRead == false) : this is more readable ;))

Categories