Here's my implementation of the Philosopher dinner concurrence problem. I works only for two threads and the rest suffers from starvation, literally ;) I appreciate if you could find the cause of it.
Here's the output:
Philosopher 2 is eating
Philosopher 0 is eating
Philosopher 2 is eating
Philosopher 0 is eating
Philosopher 2 is eating
Philosopher 0 is eating
Philosopher 2 is eating
Philosopher 0 is eating
Philosopher 2 is eating
Philosopher 2 is eating
Philosopher 0 is eating
Philosopher 2 is eating
Philosopher 0 is eating
Here's the code:
public class PhilosophersDinner {
public static void main(String[] args) {
Chopstick2[] chopsticks = new Chopstick2[5];
Philosopher [] philosophers = new Philosopher[5];
for (int i = 0; i < 5; i++) {
Chopstick2 stick = new Chopstick2();
chopsticks[i] = stick;
}
for (int i = 0; i < 5; i++) {
Philosopher philo = new Philosopher(chopsticks[i] , chopsticks[(i+1)%5], i+"");
philosophers[i] = philo;
}
for (int i = 0; i < philosophers.length; i++) {
new Thread(philosophers[i]).start();
}
}
}
class Philosopher implements Runnable {
private final Chopstick2 left;
private final Chopstick2 right;
private final String id;
public Philosopher(Chopstick2 l, Chopstick2 r, String id){
this.left = l;
this.right = r;
this.id = id;
}
public void eat(){
if (left.pickUp()) {
if (right.pickUp()) {
chew();
putDown();
} else left.putDown();
}
}
public void run(){
for (int i = 0; i < 10; i++) {
eat();
}
}
public void chew(){
try {
System.out.println("Philosopher "+id+" is eating");
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
// release lock here?
}
}
public void putDown(){
left.putDown();
right.putDown();
}
}
class Chopstick2 {
private volatile boolean taken = false;
public synchronized boolean pickUp(){
if (!taken) {
taken = true;
return true;
}
else return false;
}
public synchronized void putDown(){
taken = false;
}
}
The problem is that the first two Philosophers to get chopsticks spend half of a second eating and during that time the other three diners try to eat until they give up and quit.
One solution would be to have all of the philosophers eat for a specified amount of time instead of making a specific number of attempts to eat.
for (long i = System.currentTimeMillis()+10000; i > System.currentTimeMillis(); ) {
eat();
}
Related
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
I found on a book this alternative solution for "Dining philosopher problem", in Java:
public class Philosopher extends Thread {
private final int maxPause = 100;
private int bites = 10;
private Chopstick lower;
private Chopstick higher;
private int index;
public Philosopher(int i, Chopstick left, Chopstick right) {
index = i;
if (left.getNumber() < right.getNumber()) {
this.lower = left;
this.higher = right;
} else {
this.lower = right;
this.higher = left;
}
}
public void eat() {
System.out.println("Philosopher " + index + ": start eating");
pickUp();
chew();
putDown();
System.out.println("Philosopher " + index + ": done eating");
}
public void pickUp() {
pause();
lower.pickUp();
pause();
higher.pickUp();
pause();
}
public void chew() {
System.out.println("Philosopher " + index + ": eating");
pause();
}
public void pause() {
try {
int pause = AssortedMethods.randomIntInRange(0, maxPause);
Thread.sleep(pause);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void putDown() {
higher.putDown();
lower.putDown();
}
public void run() {
for (int i = 0; i < bites; i++) {
eat();
}
}
}
public class Chopstick {
private Lock lock;
private int number;
public Chopstick(int n) {
lock = new ReentrantLock();
this.number = n;
}
public void pickUp() {
lock.lock();
}
public void putDown() {
lock.unlock();
}
public int getNumber() {
return number;
}
}
The text of the solution is:
Alternatively, we can label the chopsticks with a number from e to N - 1. Each philosopher attempts to pick up the lower numbered chopstick first. This essentially means that each philosopher goes for the left chopstick before right one (assuming that's the way you labeled it), except for the last philosopher who does this in reverse. With this solution, a philosopher can never hold the larger chopstick without holding the smaller one. This
prevents the ability to have a cycle, since a cycle means that a higher chopstick would "point"to a lower one.
But it's not clear for me. Someone can help me with an example?
Thanks
----EDIT-----
Main class:
public class Question {
public static int size = 3;
public static int leftOf(int i) {
return i;
}
public static int rightOf(int i) {
return (i + 1) % size;
}
public static void main(String[] args) {
Chopstick[] chopsticks = new Chopstick[size + 1];
for (int i = 0; i < size + 1; i++) {
chopsticks[i] = new Chopstick(i);
}
Philosopher[] philosophers = new Philosopher[size];
for (int i = 0; i < size; i++) {
Chopstick left = chopsticks[leftOf(i)];
Chopstick right = chopsticks[rightOf(i)];
philosophers[i] = new Philosopher(i, left, right);
}
for (int i = 0; i < size; i++) {
philosophers[i].start();
}
}
}
Let's have
3 philosophers - p1,p2,p3 and 3 chopsticks c1,c2,c3 (index of chopstick is equal to number)
you create then p1(c1, c2), p2(c2, c3), p3(c1, c3)
worst case scenario:
p1 acquires lock on c1
meanwhile p2 acquires lock on c2 -> blocks p1
p3 is blocked by p1(still holding c1 lock) -> p2 is free to acquire c3
p2 acquires c3 -> finishes and releases c2 and c3
p1 acquires c2 -> finishes and releases c1 and c2
p3 acquires c1 and c3 -> finishes and releases c1 and c3
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));
}
}
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.
I'm trying to make a "X and O" game using threads. I use a char matrix[3][3] for my game table and I want the first thread to put "X" and after that to show the matrix and then the second threat to pun "O" and so on. How can I do this using threads?
public class ThreadExample implements Runnable {
private char[][] array;
private Semaphore ins, outs;
private int counter;
ThreadExample(Semaphore ins, Semaphore outs) {
this.ins = ins;
this.outs = outs;
this.counter = 0;
this.array = new char[3][3];
}
#Override
public void run() {
for (int i = 0; i < 9; i++) {
try {
ins.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
} // wait for permission to run
print();
playTurn();
outs.release(); // allow another thread to run
}
}
private void print() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
private synchronized void playTurn() {
Scanner sc = new Scanner(System.in);
int x;
int y;
System.out.println("enter the x coord: ");
x = sc.nextInt();
System.out.println("enter the y coord: ");
y = sc.nextInt();
// sc.close();
if (counter % 2 == 0) {
array[x][y] = 'X';
counter++;
} else {
array[x][y] = 'O';
counter++;
}
}
}
And this is my main
public class Main {
public static void main(String[] args) {
Semaphore a = new Semaphore(1);
Semaphore b = new Semaphore(0);
ThreadExample th1 = new ThreadExample(a, b);
Thread tr1 = new Thread(th1);
Thread tr2 = new Thread(th1);
tr1.start();
tr2.start();
}
}
This is my code so far but after the first x and y coord it stops.
The problem is here, after the first 'x,y' both threads are waiting for the 'ins' Semaphore, and no one cares about the 'outs'.
You can fix it by remove 'outs' and use only 'ins'. Here you should double check, that how acquire is implemented. Does it grantee a queue or can a thread acquire it twice rarely?