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);
}
}
Related
I have to insert the elements using three threads by creating three classes, namely Task1,Task2 and Task3. The values to be inserted into the array are 0,1,2,....299.
Override the run method in the threads. Three integer i,j, and k representing the number of elements each thread should append inside the given array.
Thread one should append 0 to i-1 inside the array,thread two should append i to i+j-1 inside the array,and the third thread should append i+j to 299 inide the array.
Threads one and two must run simultaneously, and the values of the threads one and two must be inserted inside the indices of the array from 0 to i+j-1 randomly.The third thread should start only after the first two threads have been executed completely.
In these code three task are given.
first task and second task start executing the thread at the same time and after completion of first two task then only third task start. If these situation getting correct then test() method return true.
public static final int[] threadArray = new int[300]; how I add random number into these array using Task1 Task2 and Task3 class.
Input :
80
130
90
Output :
True
import java.util.Scanner;
class Task1 extends Thread
{
static int a = 0;
static int beg = 0;
public void run()
{
for(int i=a;i<=beg;i++)
{
Solution.threadArray[i] = i;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Task2 extends Thread
{
static int a = 0;
static int beg = 0;
#Override
public void run()
{
// TODO Auto-generated method stub
for(int i=a;i<=beg;i++)
{
Solution.threadArray[i] = i;
}
}
}
class Task3 extends Thread
{
static int a = 0;
static int beg = 0;
public void run()
{
// TODO Auto-generated method stub
for(int i=a;i<=beg;i++)
{
Solution.threadArray[i] = i;
}
}
}
public class Solution
{
public static final int[] threadArray = new int[300];
public static volatile String i = 0+"";
public boolean test() throws InterruptedException
{
Task1 task1 = new Task1();
Task2 task2 = new Task2();
Task3 task3 = new Task3();
Thread task2Thread = new Thread(task2);
Thread task3Thread = new Thread(task3);
task1.start();
task2Thread.start();
task1.join();
task2Thread.join();
task3Thread.start();
int first = Task1.a+Task2.a;
int containsSecondThread = Task1.a;
String oneAndTwo = "";
String sizeOfTask1 = "";
for(int i=0;i<first;i++)
{
oneAndTwo += threadArray[i]+" ";
}
for(int i=0;i<containsSecondThread;i++)
{
sizeOfTask1 += threadArray[i]+" ";
}
int begOfTask3 = Task3.beg;
String checkingString = "";
for(int i=begOfTask3;i<threadArray.length;i++)
{
checkingString += i + " ";
}
String task3String = "";
for(int j = begOfTask3;j<threadArray.length;j++)
{
task3String += threadArray[j]+" ";
}
if((!oneAndTwo.contains(begOfTask3+"") && sizeOfTask1.contains(Task2.beg+"")) || task3String.equals(checkingString))
{
return true;
}
return false;
}
public static void main(String[] args) throws InterruptedException
{
Scanner sc= new Scanner(System.in);
Solution solution = new Solution();
int one = sc.nextInt();
Task1.a = one;
Task1.beg = 0;
int two = sc.nextInt();
Task2.a = two;
Task2.beg = one;
int three = sc.nextInt();
Task3.a = three;
Task3.beg = one+two;
System.out.print(solution.test());
}
}
First, some observations regarding your code: Instead of using static variables in the classes (i.e., Task1, Task2, and Task3) that extend the class Thread (to understand why have a look at Why are static variables considered evil?):
static int a = 0;
static int beg = 0;
use non-static final fields, and initialize them via the constructor:
class Task1 extends Thread
{
private final int begin;
private final int end;
Task1(int begin, int end){
this.begin = begin;
this.end = end;
}
public void run(){
for(int i=begin; i<= end; i++)
....
}
}
adapt the main method accordingly:
public static void main(String[] args){
...
Task1 task1 = new Task1(begin, end);
}
and then pass the tasks-related objects as parameters of to the test method:
public boolean test(Task1 task1, Task2 task2, Task3 task3){
...
}
For the concatenation of the strings use StringBuilder:
StringBuilder oneAndTwo = new StringBuilder();
for(int i=0;i<first;i++)
{
oneAndTwo.append(threadArray[i]).append(" ");
}
This looks wrong:
Task1.a = one;
Task1.beg = 0;
by looking at the loop of the run method from Task1, this means that, if Task1.a is not a negative number, then Task1 will not do any work.
To use the threads to generate the random values of the array:
int[] threadArray = new int[300];
you can start by extracting a method to generate those random values, based on formula:
r.nextInt(high-low) + low;
this formula generates a random value between low and high.
Adapt the tasks, accordingly:
class Task1 extends Thread
{
private final Random random_values = new Random();
private final int low;
private final int high;
...
public int generate_random(){
return r.nextInt(high-low) + low;
}
public void run()
{
for(....)
{
Solution.threadArray[i] = generate_random();
...
}
}
}
Make sure to pass to the threads the information about the range of the random values to be generated (i.e., the low and high parameters), and the reference to the array that will be filled up with those random values (i.e., array int[] threadArray) . Also make sure that you split the iterations int[] threadArray among the threads. Therefore, each thread should generate a chunk of the random values. An example of such distribution would be:
Thread 1 : 0 to 100;
Thread 2 : 100 to 200;
Thread 3 : 200 to 300;
You can make this more robust and divide the array length by the number to threads and assign the work among threads, accordingly.
I could have provided you with the entire solution, but I feel that is better instead if I give you the pointers so that you can do it in your own.
EDIT: Based on the new edit of your question:
You just need to adapt the Task classes as follows:
class Task1 extends Thread {
static int a = 0;
static int beg = 0;
public void run(){
for(int i=beg;i < a;i++)
Solution.threadArray[i] = i;
}
}
class Task2 extends Thread {
static int a = 0;
static int beg = 0;
public void run(){
for(int i=beg; i< beg + a;i++)
Solution.threadArray[i] = i;
}
}
class Task3 extends Thread{
static int a = 0;
static int beg = 0;
public void run(){
for(int i=beg;i< a + beg;i++)
Solution.threadArray[i] = i;
}
}
Thread1 and Thread2 are supposed to access Common Resource in threadArray[0... Task1.a+Task2+a]. So we have to make use of static volatile variable i declared in Solution Class.
class Task1 extends Thread
{
static int a=0,beg=0;
public void run()
{
int k=Task1.beg;
int i1=0;
while(i1<Task1.a)
{
Solution.threadArray[Integer.parseInt(Solution.i)]=k++;
int a1=Integer.parseInt(Solution.i);
a1++;i1++;
Solution.i=a1+"";
try{
Thread.sleep(1);
}
catch(InterruptedException e){}
}
}
}
class Task2 extends Thread
{
static int a=0,beg=0;
public void run()
{
int y=0;
int k=Task2.beg;
while(y<Task2.a)
{
Solution.threadArray[Integer.parseInt(Solution.i)]=k++;
int a1=Integer.parseInt(Solution.i);
a1++;y++;
Solution.i=a1+"";
try{
Thread.sleep(1);
}
catch(InterruptedException e){}
}
}
}
Thread3 work independently after First 2 threads complete.
class Task3 extends Thread
{
static int beg=0,a=0;
public void run()
{
for(int i=Task3.beg;i<Task3.beg+Task3.a;i++)
{
Solution.threadArray[i]=i;
}
}
}
So I am supposed to write a program, in which multiple threads add some number of items to a list. I was given two interfaces that I should implement. The number added is a sum of two previous numbers added (like Fibonacci series)
public interface Main
{
List<Integer> sum(int count, int threadCount, int firstElement, int secondElement);
}
and
public interface Sum extends Runnable
{
//how many elements each thread should add
int getHowMany();
List<Integer> getList();
}
So I thought of doing it this way: I create a class DefaultSum, which implements Sum interface, implement methods from it, and in the run() method I would call a method actually adding elements to list.
This is my DefaultSum class
public class DefaultSum implements Sum {
DefaultMain main = new DefaultMain();
DefaultSum() {
}
#Override
public void run() {
int count = getHowMany();
List<Integer> list = getList();
int firstElement = list.get(list.size() - 2).intValue();
int secondElement = list.get(list.size() - 1).intValue();
int j = 2;
while (j < count) {
int adder = firstElement + secondElement;
list.add(adder);
System.out.println(list);
firstElement = secondElement;
secondElement = adder;
if (j == count) {
notifyAll();
}
j++;
}
System.out.println(list);
}
#Override
public int getHowMany() {
try {
Field[] fields = DefaultMain.class.getFields();
for (int i = 0; i < fields.length; i++) {
Object val = fields[i].get(main);
if (fields[i].getName().equalsIgnoreCase("count")) {
int number = (Integer) val;
return number;
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return -1;
}
#Override
public List<Integer> getList() {
try {
Field[] fields = DefaultMain.class.getFields();
for (int i = 0; i < fields.length; i++) {
Object val = fields[i].get(main);
if (fields[i].getName().equalsIgnoreCase("list")) {
return (List<Integer>) val;
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
And my main class, DefaultMain, where the number of items added is given and user can decide how many threads he wants to work on this list.
public class DefaultMain implements Main {
static int firstElement = 0;
static int secondElement = 1;
static int count = 10;
public static List<Integer> lista = new ArrayList<Integer>();
public static List<Integer> list = Collections.synchronizedList(lista);
static int threadCount;
public static void main(String[] args) throws InterruptedException {
list.add(firstElement);
list.add(secondElement);
System.out.println("how many threads");
Scanner sc = new Scanner(System.in);
threadCount = sc.nextInt();
Main exa = new DefaultMain();
exa.sum(count, threadCount, firstElement, secondElement);
}
#Override
public List<Integer> sum(int count, int threadCount, int firstElement, int secondElement) {
synchronized(this.list) {
for (int i = 0; i < DefaultMain.threadCount; i++) {
new Thread(new DefaultSum()).start();
}
return list;
}
}}
I tried running this program multiple times, however, it seems that the list is not updated after first two elements are added. Seems that methods getHowMany() and getList() work fine, I'm not sure what could be wrong, I'll appreciate any answer, this problem has been bugging me for some time now.
Edit: I'll paste what I get in console
Edit2: tried changing some bits, but it does not work at all.
how many threads
4
[0, 1]
[0, 1]
[0, 1]
[0, 1]
You just need to create a single thread Executor and then from any thread call execute() with the operations you need to do on the list in a Runnable provided as the only parameter. Here is what it looks like with a lambda.
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(() -> {
int size = list.size();
list.add(list.get(size - 1) + list.get(size - 2));
});
As the JavaDoc (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor--) states "Creates an Executor that uses a single worker thread operating off an unbounded queue...Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time."
public class UnsynchronizedCounterTest{
/**
* A class representing a counter with a method for incrementing the coutner. No synchronization is used
* so this counter is not thread safe
* #author
*
*/
static class Counter{
int count;
void inc() {
count = count+1;
}
int getCount() {
return count;
}
}
static Counter counter; // The counter that will be incremented. Since it is a global static variable, it is used by all threads of type HWUExercise12_1Thread. It is shared resource
static int numberOfIncrements;
static class IncrementerThread extends Thread{
public void run() {
for (int i=0; i < numberOfIncrements; i++) {
counter.inc();
}
}
}
/**
* The main program runs in a loop until the user want to exit. Each time through the loop, it runs one experiemtn.
* It gets the number of threads and the number of increments per thread from the user. It creates and starts the
* threads, and then waits for all to finsih. It prints the fibna lvalue of the counter, as well as the expected value.
* The program ends when the user enters a number less than or equal to zero as the number of threads.
* #param Args
*/
public static void main(String Args[]){
Counter counter = new Counter();
Scanner reader = new Scanner(System.in);
while(true) {
System.out.print("Enter the number of threads");
int numberOfThreads = Integer.parseInt(reader.nextLine());
if (numberOfThreads < 0) {
break;
}do {
System.out.print("Enter the number of increments per thread");
int numberOfIncrements = reader.nextInt();
//create thread array
IncrementerThread [] threads = new IncrementerThread[numberOfThreads];
//Create a thread for each position in array
for (int i=0; i< threads.length; i++) {
threads[i] = new IncrementerThread();
}
}while (numberOfIncrements <= 0);
//start the threads
for (int i=0; i < numberOfThreads; i++) {
threads[i].start();
}
try {
for(int j=0; j< numberOfThreads; j++) {
threads[j].join();
}
System.out.println("The finanl value of the counter is" + counter.getCount());
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
For this program, I created a thread class (not thread-safe) that calls the inc () method in the nested class, a specified number of times. My program is supposed to create several threads and start them all and then wait for all the threads to terminate. I also have to print the final value of the counter. My error is that the eclipse is saying the the thread array I created, threads cannot be resolved to a variable. It's giving me an error for the lines
threads[i].start();
threads[j].join();
I'm a beginner in java and I'm not sure how to fix this issue. My question is that why is it saying threads cannot be resolved to a variable when I clearly have a thread object array? Thanks.
This is a working code:
public class UnsynchronizedCounterTest{
static Counter counter;
public static void main(String Args[]){
new UnsynchronizedCounterTest().startCounting();
}
public void startCounting() {
counter = new Counter();
Scanner reader = new Scanner(System.in);
while(true) {
System.out.print("Enter the number of threads: ");
int numberOfThreads = reader.nextInt();
if (numberOfThreads <= 0) {
break;
}
IncrementerThread [] threads;
do {
System.out.print("Enter the number of increments per thread");
numberOfIncrements = reader.nextInt();
//create thread array
threads = new IncrementerThread[numberOfThreads];
//Create a thread for each position in array
for (int i=0; i< threads.length; i++) {
threads[i] = new IncrementerThread();
}
}while (numberOfIncrements <= 0);
//start the threads
for (int i=0; i < numberOfThreads; i++) {
threads[i].start();
}
try {
for(int j=0; j< numberOfThreads; j++) {
threads[j].join();
}
System.out.println("The finanl value of the counter is: " + counter.getCount());
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
class IncrementerThread extends Thread{
#Override
public void run() {
for (int i=0; i < numberOfIncrements; i++) {
counter.inc();
}
}
}
class Counter{
int count = 0;
void inc() {
count = count+1;
}
int getCount() {
return count;
}
}
}
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 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.