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
Related
I have a multithreaded quicksort algorithm witch runs correct but then never stops executing.
I tried adding return statemants everywhere but nothing helps.
How do I stop all thread from running when they are done? Is there a way for a thread terminate its self when done?
public class Parallel {
private static final int numberOfThreads = Runtime.getRuntime().availableProcessors();
private static final int fallback = 2;
private static Executor pool = Executors.newFixedThreadPool(numberOfThreads);
//public static int[] numberArray;
public static <T extends Comparable<T>> void sort(int[] numberArray){
if(numberArray == null || numberArray.length == 0){
return;
}
final AtomicInteger count = new AtomicInteger(1);
pool.execute(new QuicksortRunnable<T>(numberArray, 0, numberArray.length-1, count));
try {
synchronized (count) {
count.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static class QuicksortRunnable<T extends Comparable<T>> implements Runnable {
private final int[] values;
private final int left;
private final int right;
private final AtomicInteger count;
public QuicksortRunnable(int[] values, int left, int right, AtomicInteger count) {
this.values = values;
this.left = left;
this.right = right;
this.count = count;
}
#Override
public void run() {
quicksort(left, right);
synchronized (count) {
// AtomicInteger.getAndDecrement() returns the old value. If the old value is 1, then we know that the actual value is 0.
if (count.getAndDecrement() == 1)
count.notify();
}
return;
}
private void quicksort(int pLeft, int pRight) {
int pivotIndex = (pRight - pLeft) / 2 + pLeft;
int pivot = values[pivotIndex];
int j = pRight;
int i = pLeft;
while (i < j) {
while (values[i] > pivot) {
i++;
}
while (values[j] < pivot) {
j--;
}
if (i <= j) {
int temp = values[i];
values[i] = values[j];
values[j] = temp;
i++;
j--;
}
}
if (count.get() >= fallback * numberOfThreads) {
if (pLeft < j){
quicksort(pLeft, j);
}
if (i < pRight) {
quicksort(i, pRight);
}
} else {
if (pLeft < j) {
count.getAndAdd(1);
pool.execute(new QuicksortRunnable<T>(values, pLeft, j, count));
}
if (i < pRight) {
count.getAndAdd(1);
pool.execute(new QuicksortRunnable<T>(values, i, pRight, count));
}
}
}
}
And my Main function
public static void main(String args[]) {
Random rand = new Random();
int length = 100000;
int[] parallelArray = new int[length];
for (int i = 0; i < length; i++) {
int temp = rand.nextInt(length);
parallelArray[i] = temp;
}
sort(parallelArray);
boolean t = check(parallelArray);
System.out.println(t);
}
Function to test if code is sorted.
public static boolean check(int[] A) {
for (int i = 0; i < A.length - 1; i++) {
// System.out.print(" " + A[i]);
if (A[i] < A[i + 1]) {
return false;
}
}
return true;
}
When you use a ExecutorService you need to call the ExecutorService.shutdown() after all tasks are submitted, then you need to wait for the pool to shut down by calling ExecutorService.awaitTermination() and supply the time to wait as parameters. This is because the pool is comprised of non-daemon threads and the jvm does not exit if there are non-daemon threads still running.
So change the this to use the ExecutorService from Executor to enable hooks:
private static ExecutorService pool = Executors.newFixedThreadPool(numberOfThreads);
Then call shutdown() in the finally block:
public static <T extends Comparable<T>> void sort(int[] numberArray) {
if (numberArray == null || numberArray.length == 0) {
return;
}
final AtomicInteger count = new AtomicInteger(1);
pool.execute(new QuicksortRunnable<T>(numberArray, 0, numberArray.length - 1, count));
try {
synchronized (count) {
count.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
pool.shutdown(); //call shutdown() here
try {
pool.awaitTermination(5, TimeUnit.MINUTES); //wait for 5 minutes
}catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
In the finally section call shutdown() to initiate a orderly shut down of the threads in the pool and as the shutdown call is not blocking the awaitTermination() has to be called for the calling thread to wait for the shut down process to finish.
Isn't 5 min to wait a bit too much?
The call to awaitTermination does not necessarily wait the full five minutes. The 5 minutes is the maximum time to wait, not the minimum. To quite the Javadoc:
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
I know it means the reference to the array is volatile not the items in the array if you declare an array volatile.
I am learning mutex algorithm, so I write some test code:
public class MutualExclusion {
static final int N = 10;
static final int M = 100000;
volatile static int count = 0;
public static void main(String[] args) {
Thread[] threads = new Thread[N];
for (int i = 0; i < N; i++) {
Thread t = new Worker(i);
threads[i] = t;
t.start();
}
for (Thread t: threads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (count != N * M) {
System.out.println("count (" + count + ") != N * M (" + String.valueOf(N * M) + ")");
}
}
static class Worker extends Thread {
int id;
Worker(int id) {
this.id = id;
}
#Override
public void run() {
for (int i = 0; i < M; i++) {
this.lock();
// critical section
count++;
if (i % 1000 == 0) {
System.out.println(this.getName() + ": " + count);
}
this.unlock();
}
}
void lock() {
filterLock();
}
void unlock() {
filterUnlock();
}
static volatile int level[] = new int[N];
static volatile int lastToEnter[] = new int[N - 1];
void filterLock() {
for (int i = 0; i < (N - 1); i++) {
level[this.id] = i;
lastToEnter[i] = this.id;
outer:
while (lastToEnter[i] == this.id) {
for (int k = 0; k < N; k++ ) {
if (k != this.id && level[k] >= i) {
continue outer;
}
}
break;
}
}
}
void filterUnlock() {
level[this.id] = -1;
}
}
}
In my first implementation of filter algorithm, I missed volatile for variable level and lastToEnter, not surprisingly, the program went into a infinite loop. After I added the missing volatile, the program can end as expected.
As I said in beginning, a volatile array doesn't mean items in the array are volatile, so why can the program end as expected after I added the missing volatile?
I asked myself this question when I was implementing another mutex algorithm which still doesn't run correctly after I added volatile keyword. I have to use a trick (Java volatile array?) to make items in the array looks like being volatile: (code below can be pasted into Worker class directly)
volatile static boolean[] b = new boolean[N];
volatile static boolean[] c = new boolean[N];
volatile static int k = 0;
void dijkstraLock() {
b[this.id] = false;
outer:
for (;;) {
if (k == this.id) {
c[this.id] = false;
c = c; // IMPORTANT! the trick
for (int i = 0; i < N; i++) {
if (i != this.id && !c[i]) {
continue outer;
}
}
break;
} else {
c[this.id] = true;
if (b[k]) {
k = this.id;
}
}
}
}
void dijkstraUnlock() {
b[this.id] = true;
c[this.id] = true;
}
Volatile arrays in Java do not contain volatile elements - but if you access them via the array reference (which is volatile) you will get a volatile read. For instance, in the code above:
static volatile int lastToEnter[] = new int[N - 1];
is a volatile write, whereas
lastToEnter[i] = this.id;
is not. however, the evaluating of the array value - such as:
lastToEnter[i] == this.id
is a volatile read - you first read the reference to the array which is volatile, and only then access the i'th element to evaluate its value.
I suspect this is the reason your execution succeeds once the array is declared as volatile.
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?
I want to run some comparison of different approaches for concurrency technique.
But it throws next exceptions:
Warmup
BaseLine : 21246915
============================
Cycles : 50000
Exception in thread "pool-1-thread-3" Exception in thread "pool-1-thread-5" java.lang.ArrayIndexOutOfBoundsException: 100000
at concurrency.BaseLine.accumulate(SynchronizationComparisons.java:89)
at concurrency.Accumulator$Modifier.run(SynchronizationComparisons.java:39)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:744)
java.lang.ArrayIndexOutOfBoundsException: 100000
at concurrency.BaseLine.accumulate(SynchronizationComparisons.java:89)
at concurrency.Accumulator$Modifier.run(SynchronizationComparisons.java:39)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:744)
Here is code:
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import java.util.*;
import static net.mindview.util.Print.*;
abstract class Accumulator {
public static long cycles = 50000L;
// Number of Modifiers and Readers during each test:
private static final int N = 4;
public static ExecutorService exec = Executors.newFixedThreadPool(N * 2);
private static CyclicBarrier barrier = new CyclicBarrier(N * 2 + 1);
protected volatile int index = 0;
protected volatile long value = 0;
protected long duration = 0;
protected String id = "error";
protected final static int SIZE = 100000;
protected static int[] preLoaded = new int[SIZE];
static {
// Load the array of random numbers:
Random rand = new Random(47);
for (int i = 0; i < SIZE; i++)
preLoaded[i] = rand.nextInt();
}
public abstract void accumulate();
public abstract long read();
private class Modifier implements Runnable {
public void run() {
for (long i = 0; i < cycles; i++)
accumulate();
try {
barrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private class Reader implements Runnable {
#SuppressWarnings("unused")
private volatile long value;
public void run() {
for (long i = 0; i < cycles; i++)
value = read();
try {
barrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
public void timedTest() {
long start = System.nanoTime();
for (int i = 0; i < N; i++) {
exec.execute(new Modifier());
exec.execute(new Reader());
}
try {
barrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
duration = System.nanoTime() - start;
printf("%-13s: %13d\n", id, duration);
}
public static void report(Accumulator acc1, Accumulator acc2) {
printf("%-22s: %.2f\n", acc1.id + "/" + acc2.id, (double) acc1.duration / (double) acc2.duration);
}
}
class BaseLine extends Accumulator {
{
id = "BaseLine";
}
public void accumulate() {
value += preLoaded[index++];
if (index >= SIZE)
index = 0;
}
public long read() {
return value;
}
}
class SynchronizedTest extends Accumulator {
{
id = "synchronized";
}
public synchronized void accumulate() {
value += preLoaded[index++];
if (index >= SIZE)
index = 0;
}
public synchronized long read() {
return value;
}
}
class LockTest extends Accumulator {
{
id = "Lock";
}
private Lock lock = new ReentrantLock();
public void accumulate() {
lock.lock();
try {
value += preLoaded[index++];
if (index >= SIZE)
index = 0;
} finally {
lock.unlock();
}
}
public long read() {
lock.lock();
try {
return value;
} finally {
lock.unlock();
}
}
}
class AtomicTest extends Accumulator {
{
id = "Atomic";
}
private AtomicInteger index = new AtomicInteger(0);
private AtomicLong value = new AtomicLong(0);
public void accumulate() {
// Oops! Relying on more than one Atomic at
// a time doesn't work. But it still gives us
// a performance indicator:
int i = index.getAndIncrement();
value.getAndAdd(preLoaded[i]);
if (++i >= SIZE)
index.set(0);
}
public long read() {
return value.get();
}
}
public class SynchronizationComparisons {
static BaseLine baseLine = new BaseLine();
static SynchronizedTest synch = new SynchronizedTest();
static LockTest lock = new LockTest();
static AtomicTest atomic = new AtomicTest();
static void test() {
print("============================");
printf("%-12s : %13d\n", "Cycles", Accumulator.cycles);
baseLine.timedTest();
synch.timedTest();
lock.timedTest();
atomic.timedTest();
Accumulator.report(synch, baseLine);
Accumulator.report(lock, baseLine);
Accumulator.report(atomic, baseLine);
Accumulator.report(synch, lock);
Accumulator.report(synch, atomic);
Accumulator.report(lock, atomic);
}
public static void main(String[] args) {
int iterations = 5; // Default
if (args.length > 0) // Optionally change iterations
iterations = new Integer(args[0]);
// The first time fills the thread pool:
print("Warmup");
baseLine.timedTest();
// Now the initial test doesn't include the cost
// of starting the threads for the first time.
// Produce multiple data points:
for (int i = 0; i < iterations; i++) {
test();
Accumulator.cycles *= 2;
}
Accumulator.exec.shutdown();
}
}
How to solve this trouble?
The array preLoaded is of size 100000. So, the valid index starts from 0 to 99999 since array index starts from 0. You need to swap the statements in method accumulate()
Change this
value += preLoaded[index++]; //index validity is not done
if (index >= SIZE)
index = 0;
to
if (index >= SIZE)
index = 0;
value += preLoaded[index++]; // index validity is done and controlled
This will not make the index go to 100000. It will make it to 0 when it turns 100000 before the index value is accessed.
Note : The above code is vulnerable only in multi-threaded environment. The above code will work fine with single thread.
Change BaseLine class and AtomicTest class:
class BaseLine extends Accumulator {
{
id = "BaseLine";
}
public void accumulate() {
int early = index++; // early add and assign to a temp.
if(early >= SIZE) {
index = 0;
early = 0;
}
value += preLoaded[early];
}
public long read() {
return value;
}
}
class AtomicTest extends Accumulator {
{
id = "Atomic";
}
private AtomicInteger index = new AtomicInteger(0);
private AtomicLong value = new AtomicLong(0);
public void accumulate() {
int early = index.getAndIncrement();
if(early >= SIZE) {
index.set(0);
early = 0;
}
value.getAndAdd(preLoaded[early]);
}
public long read() {
return value.get();
}
}
I suspect that you're running into concurrent executions of BaseLine.accumulate() near the boundary of the preLoaded array.
You've got 4 threads hammering away at an unsynchronized method, which is potentially leading to index being incremented to 100000 by say, Thread 1, and before Thread 1 can set it back to 0, one of Thread 2, 3 or 4 is coming in and attempting to access preLoaded[index++], which fails as index is still 100000.
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();
}