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.
Related
My question is: how can I see the Tuple result in the process method if it was created in the check method? How am I able to use it there, if it was created in a private method?
public class Problem13 {
private Tuple<Integer> costs;
private Tuple<String> names;
private Tuple<Integer> result;
private int budget;
private int minDelta, minCost, totalCost;
public void process(String fileName) {
if (!read(fileName))
return;
if (budget >= totalCost) {
System.out.println("You can buy all items");
return;
}
if (budget < minCost) {
System.out.println("You cannot buy items");
return;
}
minDelta = -1;
int n = costs.getLength();
Set<Integer> interval = new IntegerInterval(0, n - 1);
for (int k = n - 1; k > 0; --k) {
Combinations<Integer> combinations = new Combinations<Integer>(interval, k);
combinations.produce((tuple) -> !check(tuple));
if (minDelta == 0)
break;
}
if (result == null)
System.out.println("No solution found");
else {
int k = result.getLength();
for (int j = 0; j < k; ++j)
System.out.printf("%s ", names.get(result.get(j)));
System.out.printf("(%d)\n", minDelta);
}
}
public static void main(String[] args) {
new Problem13().process("data/input13.txt");
}
private boolean check(Tuple<Integer> tuple) {
int k = tuple.getLength();
int currentCost = 0;
for (int i = 0; i < k; ++i) {
int j = tuple.get(i);
currentCost += costs.get(j);
if (currentCost > budget)
return false;
}
int d = budget - currentCost;
if (minDelta < 0 || d < minDelta) {
minDelta = d;
result = new ArrayTuple<>(k);
for (int i = 0; i < k; ++i)
result.set(i, tuple.get(i));
}
return minDelta == 0;
}
private means private to the class. So Problem13 can see anything defined in that class, whether private, public, protected or package private.
Also, the access modifier of the method only affects who can call it, not where the results can be seen. For instance, if result was defined as a public field, any class (not just Problem13) could see it.
You can find many good breakdowns of access modifiers out there on the Interwebs. Here's one.
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.
For my parallel computing class I have to think and create a parallel implementation of the selection sort algorithm. The idea is to be able to scale it to multiple threads so that it becomes faster than the serial implementation.
My idea was as follows:
Parallel selection sort idea
I have created the following implementation over the last few days but it is much slower than the serial algorithm. Whenever I use more threads it is also much slower vs when I use one thread. This is the first time I am working with threads as well so I am not sure if I implemented that correctly.
SelectionSort.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SelectionSort {
private static final int availableProcessors = Runtime.getRuntime().availableProcessors();
private static final int NUMBER_COUNT = 10000;
private static List<Integer> sortedList = new ArrayList<>();
private static int[][] splitArray;
private static List<Integer> lowestNumbers = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
List<Integer> numbers = Numbers.GenerateNumber(NUMBER_COUNT);
class Lowest {
synchronized int getLowest(int index) {
int lowestInArray = Integer.MAX_VALUE;
for (int i = 0; i < splitArray[index].length; i++) {
if (splitArray[index][i] < lowestInArray) {
lowestInArray = splitArray[index][i];
}
}
return lowestInArray;
}
}
Lowest lowest = new Lowest();
class SelectionSortThread extends Thread {
private int splitArrayIndex;
private SelectionSortThread(int splitArrayIndex) {
this.splitArrayIndex = splitArrayIndex;
}
public void run() {
lowestNumbers.add(lowest.getLowest(splitArrayIndex));
}
}
long startingTime = System.currentTimeMillis();
for (int i = 0; i < NUMBER_COUNT; i++) {
List<Thread> threads = new ArrayList<>();
splitArray = fillSplitArray(availableProcessors, numbers);
lowestNumbers.clear();
for (int j = 0; j < availableProcessors; j++) {
if(splitArray[j] != null) {
threads.add(new SelectionSortThread(j));
}
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
int lowestInArray = getLowest(lowestNumbers);
numbers = swap(numbers, lowestInArray);
sortedList.add(numbers.get(0));
numbers.remove(0);
}
System.out.println("Sorted list: " + Arrays.toString(sortedList.toArray()));
System.out.println(System.currentTimeMillis() - startingTime);
}
private static int getLowest(List<Integer> lowestNumbers) {
int lowestInArray = Integer.MAX_VALUE;
for (Integer lowestNumber : lowestNumbers) {
if (lowestNumber < lowestInArray) {
lowestInArray = lowestNumber;
}
}
return lowestInArray;
}
private static List<Integer> swap(List<Integer> list, int lowest)
{
int n = list.size();
for(int i = 0; i < n; i++)
{
if(list.get(i) == lowest) {
Collections.swap(list, 0, i);
return list;
}
}
return null;
}
static int[][] fillSplitArray(int arrayAmount, List<Integer> listToUse) {
if (listToUse.size() == 0) {
return new int[0][0];
}
int splitLength = (int) Math.ceil((double) listToUse.size() / (double) arrayAmount);
int[][] splits = new int[arrayAmount][];
int j = 0;
int k = 0;
for (int i = 0; i < listToUse.size(); i++) {
if (k == splitLength) {
k = 0;
j++;
}
if (splits[j] == null) {
int remainingNumbers = listToUse.size() - i;
splits[j] = new int[Math.min(remainingNumbers, splitLength)];
}
splits[j][k++] = listToUse.get(i);
}
return splits;
};
}
Numbers.java
import java.util.ArrayList;
import java.util.List;
class Numbers {
static List<Integer> GenerateNumber(int numberCount) {
List<Integer> temp = new ArrayList<>();
for (int i = numberCount; i > 0; i--) {
temp.add(i);
}
return temp;
}
}
Is there anything I am doing totally wrong or that I could improve? I am expecting the parallel implementation to be faster than the serial one but so far this is not the case. It is currently a lot slower.
I have a problem that I'm working on where I need to:
Initialize an array of any given size, where each value of the array will be assigned by 1 thread. So there are as many threads as the length of the array. This has to be done using a static field and cannot be done through a thread constructor
Sequentially sum the array (from 0 to n) using each each thread, cannot make thread wait if it isn't the next thread to sum, must use a wait/notify.
Could anyone provide some general direction how I could accomplish this? Right now there are problems with synchronization and I'm not sure how to solve them, sometimes values in the array are input as 0 or the summing isn't correct.
public class Processor {
static volatile int numberOfValues = 17;
static double processedArray[];
static Thread threadsArray[];
static volatile int sum;
static Object lock1 = new Object();
static Object lock2 = new Object();
Adding values to the array. Sometimes zeroes are added instead of the next number from numberOfValues
private static void initializeArray() {
threadsArray = new Thread[numberOfValues];
processedArray = new double[numberOfValues];
for (int i = 0; i < threadsArray.length; i++) {
threadsArray[i] = new Thread(new Runnable() {
public void run() {
synchronize(lock1) {
processedArray[numberOfValues - 1] = numberOfValues;
numberOfValues--;
}
}
});
threadsArray[i].start();
}
for (int i = 0; i < threadsArray.length; i++) {
try {
threadsArray[i].join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Summing the values in the array, doesn't always sum to be correct (in this case where the sum is all numbers from 1-17)
for (int i = 0; i < threadsArray.length; i++) {
threadsArray[i] = new Thread(new Runnable() {
public void run() {
synchronize(lock2) {
sum += processedArray[numberOfValues];
numberOfValues++;
}
}
});
threadsArray[i].start();
}
for (int i = 0; i < threadsArray.length; i++) {
try {
threadsArray[i].join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Main
public static void main(String args[]) {
initializeArray();
for (int i = 0; i < threadsArray.length; i++) {
System.out.println(processedArray[i]);
}
System.out.println("Sum: " + sum);
}
}
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.