Is there an issue with the synchronized methods in monitor? - java

Im trying to write kind of "Merge Sort" using threads in Java. Basically Monitor class gets an array and creates an Array Stack which contains arrays of length 1.
Monitor has 3 functions synchronized:
getSubArray - gets an subarray from stack, if the stack is empty it just waits.
setSubArray - push an subarray to stack, and notify all threads.
canContinue - check if the if we finished sorting the array.
Monitor Class:
public class MergeSort {
private Stack<int[]> subArrays;
private int arraySize;
public MergeSort(int[] array)
{
this.subArrays = new Stack<int[]>();
this.arraySize = array.length;
for (int i = 0; i < array.length; i++) {
int[] temp = new int[1];
temp[0] = array[i];
this.subArrays.push(temp);
}
}
public synchronized void setSubArray(int[] newSubArray,String threadName)
{
this.subArrays.push(newSubArray);
System.out.println(threadName+ " pushing new array to Stack, and notifying all threads");
notifyAll();
}
public synchronized boolean canContinue() {
if(this.subArrays.peek()==null)
try {
wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
return this.subArrays.peek() != null && this.subArrays.peek().length < arraySize;
}
public synchronized int[] getSubArray(String threadName)
{
while(this.subArrays.isEmpty()) {
try {
System.out.println(threadName+ ": subarrays is empty.... going to wait");
wait();
System.out.println(threadName+ ": i got notified, continuing getting a subarray");
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
return subArrays.pop();
}
}
Thread Class
public class Sorter extends Thread {
private MergeSort arrayToSort;
private String threadName;
private int[] subArray1;
private int[] subArray2;
public Sorter(MergeSort arrayToSort,String name)
{
this.arrayToSort=arrayToSort;
this.threadName = name;
}
public void run() {
super.run();
while(this.arrayToSort.canContinue())
{
this.subArray1 = this.arrayToSort.getSubArray(this.threadName);
System.out.println(this.threadName+": subArray1 was set successfully");
this.subArray2 = this.arrayToSort.getSubArray(this.threadName);
System.out.println(this.threadName+": Got two sub arrays:\n"+ "\tSubArray1: "+ Arrays.toString(subArray1)+
"\n\tSubArray2: "+ Arrays.toString(subArray2));
int[] subSortedArray=mergeSubArraySorted(this.subArray1,this.subArray2);
System.out.println(this.threadName+ ": Merged two sub arrays: "+ Arrays.toString(subSortedArray));
this.arrayToSort.setSubArray(subSortedArray,this.threadName);
}
System.out.println(this.threadName+": Oh wow, we finished sorting the array :D");
}
public int[] mergeSubArraySorted(int[] subArray1, int[] subArray2)
{
int subArraySortedLength = subArray1.length +subArray2.length;
int[] subArraySorted = new int[subArraySortedLength];
for (int i = 0; i < subArraySorted.length; i++) {
if(i < subArray1.length){
subArraySorted[i] = subArray1[i];
}
else{
subArraySorted[i] = subArray2[i - subArray1.length];
}
}
Arrays.sort(subArraySorted);
return subArraySorted;
}
}
Main
public class Main {
public static void main(String[] args) {
int[] arrayToSort = {4,5,1};
MergeSort merge = new MergeSort(arrayToSort);
Sorter sort1 = new Sorter(merge,"sort1");
Sorter sort2 = new Sorter(merge,"sort2");
sort1.start();
sort2.start();
}
}
The issue I see is that while 2 threads are running, thread1 is waiting in getSubArray and while thread2 is doing his work and then push the sorted. thread2 goes to getSubArray and "steal" the array from thread1. As you see in (row5) Sort1 is in getSubArray and waiting for Sort2 to push to Stack.(row6,7) Sort2 push to stack but it continues and goes to GetSubArray which is synchronized .
the output:
1. sort2: subArray1 was set successfully
2. sort2: Got two sub arrays:
SubArray1: [5]
SubArray2: [4]
3. sort1: subArray1 was set successfully
4. sort2: Merged two sub arrays: [4, 5]
5. sort1: subarrays is empty.... going to wait
6. sort2 pushing new array to Stack, and notifying all threads
7. sort2: subArray1 was set successfully
8. sort1: i got notified, continuing getting a subarray
9. sort1: subarrays is empty.... going to wait
10. sort2: subarrays is empty.... going to wait

Related

Prime Numbers Generating Threads in Java printing twice

I am trying to print prime numbers between one point to another, lets say from 1 to 1000 in one thread and 1000 to 2000 in another thread but when I print each thread using foreach loop it gives me an unordered Arraylist which is printed twice.
I am trying to print 1, 2, 3, 5, 7... using two concurrent threads. Please help me out so that I can better understand threading.
public class PrimeNumberGenerator implements Runnable{
protected long from, to;
static ArrayList<Long> primeList = new ArrayList<Long>();
public PrimeNumberGenerator(long from,long to)
{
this.from = from;
this.to = to;
}
public long count = 0;
public void run() {
for(long n=from; n<=to; n++){
boolean isPrime = true;
for(long i = 2; i<n; i++) {
if(n % i==0) {
isPrime = false;
break;
}
}
if(isPrime) {
count++;
primeList.add(n);
}
}
}
public ArrayList<Long> getPrimes() {
return primeList;
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
PrimeNumberGenerator gen1 = new PrimeNumberGenerator(1L,1000L);
PrimeNumberGenerator gen2 = new PrimeNumberGenerator(1001L,2000L);
Thread t1 = new Thread(gen1);
Thread t2 = new Thread(gen2);
t1.start();
t2.start();
t1.join();
t2.join();
gen1.getPrimes().forEach(primeList -> System.out.println(primeList));
gen2.getPrimes().forEach(primeList -> System.out.println(primeList));
}
}
The problem is that you have two threads filling the same ArrayList at the same time, because your ArrayList is static (meaning there will only be one instand shared throughout the whole application)
The first thread may add three numbers, then the second thread adds three numbers and then the first again, resulting in an ArrayList that contains
[1, 2, 3, 1009, 1013, 1019, 5, 7, 11]
Then in the end you (correctly) wait for the Threads to finish and print the same (incorrectly ordered) ArrayList twice!
Just make your ArrayList non static and it will work, that way both PrimeNumberGenerator will have their own ArrayList!
I recommend using a TreeSet to keep the primes ordered. The TreeSet will need to be properly synchronized for multiple thread access.
public class PrimeNumberGenerator implements Runnable {
protected long from, to;
static Set<Long> primeList = new TreeSet<Long>();
public PrimeNumberGenerator(long from, long to)
{
this.from = from;
this.to = to;
}
public long count=0;
public void run() {
for(long n=from;n<=to;n++) {
boolean isPrime = true;
for(long i = 2; i<n; i++) {
if(n % i==0) {
isPrime = false;
break;
}
}
if(isPrime) {
count++;
synchronized(primeList) {
primList.add(n);
}
}
}
}
public static ArrayList<Long> getPrimes(){
//Make a copy so we don't need to synchronize outside of this class
return new ArrayList<>(primeList);
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
PrimeNumberGenerator gen1 = new PrimeNumberGenerator(1L,1000L);
PrimeNumberGenerator gen2 = new PrimeNumberGenerator(1001L,2000L);
Thread t1 = new Thread(gen1);
Thread t2 = new Thread(gen2);
t1.start();
t2.start();
t1.join();
t2.join();
PrimeNumberGenerator.getPrimes().forEach(primeList -> System.out.println(primeList));
}
}

Erastotenes Sieve in paraller programm Java

I would like to make a programm which count prime numbers using Erastotenes Sieve. In this issue I want to use semaphore to communicate between thread to make calculations on table with numbers.
So far I have written code like that.
public static void main( String[] args ) throws InterruptedException {
System.out.println("Podaj gorny zakres\n");
Scanner scanner = new Scanner(System.in);
Erastotenes erastotenes = new Erastotenes(Integer.parseInt(scanner.nextLine()));
erastotenes.initializeTable();
long start = System.nanoTime();
List<SingleProcess.MyThread> list = new ArrayList<>();
List<Integer> numbers = Dollar.$(2,erastotenes.getMaximumNumber()+1).toList();
for(int i=0;i<2;i++)
{
list.add(new SingleProcess.MyThread(erastotenes,numbers.subList((numbers.size()/2)*i,(numbers.size()/2)*i+numbers.size()/2)));
list.get(list.size()-1).start();
list.get(list.size()-1).join();
}
System.out.println(System.nanoTime() - start);
//System.out.println("Liczba elementów: "+erastotenes.countPrimeElements());
}
Erastotenes class.
public class Erastotenes {
private int upperRange;
private int maximumNumber;
private int table[];
public Erastotenes(int upperRange) {
this.upperRange = upperRange;
this.maximumNumber = (int)(Math.floor(Math.sqrt(upperRange)));
this.table = new int[upperRange+1];
}
public int getMaximumNumber() {
return maximumNumber;
}
public int getUpperRange() {
return upperRange;
}
public void initializeTable()
{
for(int i=1;i<=upperRange;i++) {
table[i] = i;
}
}
public void makeSelectionOfGivenNumber(int number)
{
if (table[number] != 0) {
int multiple;
multiple = number+number;
while (multiple<=upperRange) {
table[multiple] = 0;
multiple += number;
}
}
}
public List<Integer> getList()
{
List<Integer> list = Ints.asList(table);
return list.stream().filter(item->item.intValue()!=0 && item.intValue()!=1).collect(Collectors.toList());
}
}
The class describing single Thread to make calculations with static Semaphore looks like this.
public class SingleProcess {
static Semaphore semaphore = new Semaphore(1);
static class MyThread extends Thread {
Erastotenes erastotenes;
List<Integer> numbers;
MyThread(Erastotenes erastotenes,List<Integer> numbers) {
this.erastotenes = erastotenes;
this.numbers=numbers;
}
public void run() {
for(int number:numbers) {
try {
semaphore.acquire();
//1System.out.println(number + " : got the permit!");
erastotenes.makeSelectionOfGivenNumber(number);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}
}
}
}
I thought that splitting on half table with numbers from 2 to maximum numbers as square root like in erastotrenes algorithm for these two Threads will boost calculations, but with upperRange to 100000000 the difference between paraller and sequence is not so big. How can I in another realize this problem of paraller programming Erastotenes Sieve?
I think your main problem is this:
for(int i=0;i<2;i++)
{
list.add(new SingleProcess.MyThread(erastotenes,numbers.subList((numbers.size()/2)*i,(numbers.size()/2)*i+numbers.size()/2)));
list.get(list.size()-1).start();
list.get(list.size()-1).join();
}
You start a thread and then immediately wait for it to finish; that kills the parallelism entirely. You can start and wait in the end:
for(int i=0;i<2;i++)
{
list.add(new SingleProcess.MyThread(erastotenes,numbers.subList((numbers.size()/2)*i,(numbers.size()/2)*i+numbers.size()/2)));
list.get(list.size()-1).start();
}
for (Thread t : list) {
t.join();
}
But, there's also a problem with your semaphore tbh. Each thread blocks all other threads from doing anything as long as it's working on a number; that means that again, all parallelism is gone.
You can do away with the semaphore altogether IMO; there's not really a lot of danger in setting the same index to 0 several times, which is all that happens in this "critical section" - but it's not critical at all because no one ever reads the array value in question before all threads are finished.

some elements processed more than once, some not at all

I have a fairly straightforward task: I have a list of strings each of which is processed and a score is produced. The string and its score then get added to a map:
public class My1Thread
{
final private static List<String> ids = Arrays.asList("id1","id2","id3","id4","id5");
private static HashMap<String,Double> result = null;
private Double computeResult(String id)
{
Double res = 0.0;
// do stuff to compute result
return res;
}
public static void main(String[] args)
{
result = new HashMap<String,Double>();
for (String id: ids)
{
result.put(id,computeResult(id));
}
}
}
Since scores of any two strings are independent of each other, this seems to be a perfect case to use multithreading. However, I am getting unexpected results, which is probably a typical result for a multithreading newbie.
Here's a m/t version of the above:
public class MyMultiThread
{
final private static int nWorkers = 3; // number of threads
final private static List<String> ids = Arrays.asList("id1","id2","id3","id4","id5");
private static int curIndex = 0; // indexing pointing to position in ids currently being processed
private static HashMap<String,Double> result = null;
public static class Worker implements Runnable {
private int id;
public Worker(int id) {
this.id = id;
}
synchronized void setCounter(final int counter)
{
curIndex = counter;
}
synchronized int getCounter()
{
return curIndex;
}
synchronized void addToResult(final String id, final Double score)
{
result.put(id,score);
}
#Override
public void run()
{
try {
while (true)
{
int index = getCounter();
if (index >= ids.size())
{
// exit thread
return;
}
String id = ids.get(index);
setCounter(index+1);
System.out.print(String.format("Thread %d: processing %s from pos %d\n", id, id, curIndex-1));
Double score = ... // compute score here
addToResult(id,score);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public static void main(String[] args)
{
result = new HashMap<String,ArrayList<Pair<Document,Double>>>();
for (int i = 0; i < nWorkers; i++) {
Thread worker = new Thread(new MyMultiThread.Worker(i));
worker.start();
}
}
}
According to the output produced by System.out.print, this code appears to be processing some elements of ids more than once while not processing others at all. What am I doing wrong here?
Your while(true) loop inside the thread starts at the index specified in the constructor, and then increment it by one, and then the loop starts again. So thread 0 does index 0, then index 1, etc.. Thread 1 does index 1, then index 2, etc... So index 2 will be done 3 times.
I would use a synchronized linked list for ids, and have each thread take and remove the first element of the list, until the list is empty. Use LinkedList.removeFirst().
Also the result hash map also needs to be synchronized, since multiple threads may write to it at the same time.
The problem is that the map is being modified concurrently in multiple threads, so some updates are getting lost.
You declared the methods that modify the map as synchronized, but note that they are synchronized on multiple worker objects: not on a single object, which would provide the locking you are after.
I'd recommend using ConcurrentHashMap and getting rid of all the synchronized declarations.
Some of your synchronization is too narrow - for example, this bit here:
int index = getCounter();
if (index >= ids.size())
{
// exit thread
return;
}
String id = ids.get(index);
setCounter(index+1);
What happens if thread A reads the counter, thread B reads the counter, then thread A updates the counter?
A: int index = getCounter(); // returns 3
B: int index = getCounter(); // returns 3
...
A: setCounter(index + 1); // sets it to 4
B: setCounter(index + 1); // Uh-oh, sets it to 4 as well, we lost an update!
In this case, when you read a variable, then write to it based on the value you read, both the read and the write need to be within the same synchronization block. Declaring getCounter and setCounter as synchronized is not enough.
Simply use Java 8 Stream API :
Map<String, Double> map = ids.parallelStream().collect(Collectors.toConcurrentMap(id -> id, id -> computeScore(id)));
...
Double computeScore(String id) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return ThreadLocalRandom.current().nextDouble(100);
}
Here's a nice tutorial.

Merge-sort using Multi-threading

I tried to parallelize merge-sort using multi-threading.Here is my code (please forgive if it poorly implemented.I did not care about the space-complexity of the program). I am achieving the sorted array.My question is:Will this process actually reduce the time taken to sort an array of large size?What all modifications are needed to make it efficient and is it o any use?
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class Merge {
public static int[] inputArray;
public static int[] arr1;
public static int[] arr2;
public static int[] arr3;
public static int t1_status=0;
public static int t2_status=0;
public static void main(String[] args) throws IOException{
System.out.println("Enter the length of the array");
Scanner in =new Scanner(System.in);
int arraySize=in.nextInt();
inputArray = new int[arraySize];
Random rand=new Random();
for(int i=0;i<arraySize;i++)
{
inputArray[i]=rand.nextInt(100);
}
//diving the original array into two subarrays
arr1=Arrays.copyOfRange(inputArray, 0, inputArray.length/2);
arr2=Arrays.copyOfRange(inputArray, (inputArray.length)/2,inputArray.length);
//printing the original array
System.out.print("The original array is array is ");
for(int h:inputArray)
{
System.out.println(h);
}
Thread t1=new Thread(new Runnable(){
public void run()
{
mergeSort(arr1);
System.out.println("t1 started");
}
});
Thread t2=new Thread(new Runnable(){
public void run()
{
mergeSort(arr2);
System.out.println("t2 started");
}
});
//starting threads
t1.start();
t2.start();
try {
t1.join();
t2.join();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(t1.isAlive())
{
t1_status=1;
}
if(t2.isAlive())
{
t2_status=1;
}
t1.stop();
t2.stop();
arr3=new int[inputArray.length];
merge(arr3,arr1,arr2);//merging arr1 and arr2.At this point both arr1 and arr2 are sorted.
System.out.println("The sorted array is ");
for(int m:arr3)
{
System.out.print(m);
System.out.print(" ");
}
System.out.println(" ");
}
static void mergeSort(int[] A)
{
if (A.length > 1)
{
int q = A.length/2;
int[] leftArray = Arrays.copyOfRange(A, 0, q);
int[] rightArray = Arrays.copyOfRange(A,q,A.length);
mergeSort(leftArray);
mergeSort(rightArray);
merge(A,leftArray,rightArray);
}
}
//merge function
static void merge(int[] a, int[] l, int[] r) {
int totElem = l.length + r.length;
int i,li,ri;
i = li = ri = 0;
while ( i < totElem) {
if ((li < l.length) && (ri<r.length)) {
if (l[li] < r[ri]) {
a[i] = l[li];
i++;
li++;
}
else {
a[i] = r[ri];
i++;
ri++;
}
}
else {
if (li >= l.length) {
while (ri < r.length) {
a[i] = r[ri];
i++;
ri++;
}
}
if (ri >= r.length) {
while (li < l.length) {
a[i] = l[li];
li++;
i++;
}
}
}
}
if(t1_status==1){arr1=a;}
else if(t2_status==1){arr2=a;}
else{arr3=a;}
}
}
Yes it can help, quite a bit depending on how many cores do you have and how big your array is. Spawning threads and coordinating work isn't free. There's a soft spot on how many parallel threads are actually useful.
I think you're doing too little,but this is very easy to overdo: Since the process is CPU-bound you want one thread for each core.
A fixed thread pool/executor is handy here.
Check out some example performance gains at CSE373:Data Structures and Algorithms/MergeSort.
Sorting both halves in separate threads is a good start, but you can make use of parallelism through the merging, too.
Also, you should recurse do the subsorts in parallel, too... BUT keep track of the depth of recursion, and stop making new threads when you're already using all your cores. Making new threads for those tiny little leaf sorts is a huge overhead.
All together:
Split into 2 threads
First, Thread 1 sorts the front half of the source array and Thread 2 sorts the back half of the source array. To sort the haves, they either call this function recursively or switch to a serial sort if 2^recursion_depth > number_of_cores; then
Thread 1 does a forward merge of both halves into the front half of the destination, and Thread 2 does a backward merge of both halves into the back half of destination. They both stop when they reach the midpoint of the destination.
See the Collections.parallelSort() and the Fork/Join framework javadoc.
The small enough arrays are sorted as legacy on single thread, but when large enough (8192, I think), the parallelSort will divide and conquer, with the ForkJoinPool default pool (as many threads as there are cores).
Using only 2 threads is probably doubling your speed, but not more.
FYI, the launcher thread should work too, not just sit there joining. It can take the job of the 2nd thread for instance. Then only join once.

Circular Buffer with Threads Consumer and Producer: it get stucks some executions

I'm developing a circular buffer with two Threads: Consumer and Producer.
I'm using active waiting with Thread.yield.
I know that it is possible to do that with semaphores, but I wanted the buffer without semaphores.
Both have a shared variable: bufferCircular.
While the buffer is not full of useful information, producer write data in the position pof array, and while there are some useful information consumer read data in the position c of array. The variable nElem from BufferCircular is the number of value datas that haven't been read yet.
The program works quite good 9/10 times that runs. Then, sometimes, it get stucks in a infinite loop before show the last element on screen (number 500 of loop for), or just dont' show any element.
I think is probably a liveLock, but I can't find the mistake.
Shared Variable:
public class BufferCircular {
volatile int[] array;
volatile int p;
volatile int c;
volatile int nElem;
public BufferCircular(int[] array) {
this.array = array;
this.p = 0;
this.c = 0;
this.nElem = 0;
}
public void writeData (int data) {
this.array[p] = data;
this.p = (p + 1) % array.length;
this.nElem++;
}
public int readData() {
int data = array[c];
this.c = (c + 1) % array.length;
this.nElem--;
return data;
}
}
Producer Thread:
public class Producer extends Thread {
BufferCircular buffer;
int bufferTam;
int contData;
public Productor(BufferCircular buff) {
this.buffer = buff;
this.bufferTam = buffer.array.length;
this.contData = 0;
}
public void produceData() {
this.contData++;
this.buffer.writeData(contData);
}
public void run() {
for (int i = 0; i < 500; i++) {
while (this.buffer.nElem == this.bufferTam) {
Thread.yield();
}
this.produceData();
}
}
}
Consumer Thread:
public class Consumer extends Thread {
BufferCircular buffer;
int cont;
public Consumer(BufferCircular buff) {
this.buffer = buff;
this.cont = 0;
}
public void consumeData() {
int data = buffer.readData();
cont++;
System.out.println("data " + cont + ": " + data);
}
public void run() {
for (int i = 0; i < 500; i++) {
while (this.buffer.nElem == 0) {
Thread.yield();
}
this.consumeData();
}
}
}
Main:
public class Main {
public static void main(String[] args) {
Random ran = new Random();
int tamArray = ran.nextInt(21) + 1;
int[] array = new int[tamArray];
BufferCircular buffer = new BufferCircular(array);
Producer producer = new Producer (buffer);
Consumer consumer = new Consumer (buffer);
producer.start();
consumer.start();
try {
producer.join();
consumer.join();
} catch (InterruptedException e) {
System.err.println("Error with Threads");
e.printStackTrace();
}
}
}
Any help will be welcome.
Your problem here is that your BufferCircular methods are sensitive to race conditions. Take for example writeData(). It executes in 3 steps, some of which are also not atomic:
this.array[p] = data; // 1
this.p = (p + 1) % array.length; // 2 not atomic
this.nElem++; // 3 not atomic
Suppose that 2 threads entered writeData() at the same time. At step 1, they both have the same p value, and both rewrite array[p] value. Now, array[p] is rewritten twice and data that first thread had to write, is lost, because second thread wrote to the same index after. Then they execute step 2--and result is unpredictable since p can be incremented by 1 or 2 (p = (p + 1) % array.length consists of 3 operations, where threads can interact). Then, step 3. ++ operator is also not atomic: it uses 2 operations behind the scenes. So nElem becomes also incremented by 1 or 2.
So we have fully unpredictable result. Which leads to poor execution of your program.
The simplest solution is to make readData() and writeData() methods serialized. For this, declare them synchronized:
public synchronized void writeData (int data) { //...
public synchronized void readData () { //...
If you have only one producer and one consumer threads, race conditions may occur on operations involving nElem. Solution is to use AtomicInteger instead of int:
final AtomicInteger nElem = new AtomicInteger();
and use its incrementAndGet() and decrementAndGet() methods.

Categories