I would like to simulate a situation which is mentioned in books about concurrency - that without a proper synchronization one thread can see a stale value of a variable that has been already modified by a different thread. This could happen because for example a CPU cache.
To do this I have written the following program. The idea is that there are 4 threads that initialize a different part of a shared array. The 5th thread (main, parent thread) waits until all 4 previous threads are done, iterates over the shared array and adds its values (always 1 or if I'm lucky null, which would mean a stale value)
package p1;
class ArrFill implements Runnable {
int l, r;
Integer[] arr;
ArrFill(int l, int r, Integer[] arr) {
this.l = l;
this.r = r;
this.arr = arr;
}
#Override
public void run() {
for(int i = l; i < r; i++)
arr[i] = new Integer(1);
}
}
public class Main {
final static int MAX = 10000000;
final static int tnum = 4;
public static void main(String[] args) throws InterruptedException {
int cores = Runtime.getRuntime().availableProcessors();
System.out.println(cores);
Integer[] arr = new Integer[MAX];
Thread[] t = new Thread[tnum];
if(MAX % tnum != 0)
throw new IllegalStateException();
int step = MAX / tnum;
int l = 0, r = 0;
for(int i = 0; i < tnum; i++) {
l = r;
r += step;
t[i] = new Thread(new ArrFill(l, r, arr));
t[i].start();
}
for(int i = 0; i < tnum; i++)
t[i].join();
int res = 0;
for(int i = 0; i < MAX; i++)
if(arr[i] != null)
res += arr[i];
System.out.println(res == MAX);
}
}
I have run this program many times although I never seen a stale value (null). I have 2 cores. Do you have any idea how this program could be improved to actually present the cached value phenomena? Or maybe you have a completly different approach?
Thanks!
Related
The followiing code uses threads to calculate the max value in a subarry, and then calculates the max value out of the max values the threads returned. I have a bug that the main thread doesn't wait for the threads to finish when collecting the results.
Thread class:
public class MaxTask extends Thread {
private int[] arr;
private int max;
private int first, last;
public MaxTask(int[] arr, int first, int last) {
this.arr = arr;
this.first = first;
this.last = last;
}
public int getMax() {
return max;
}
public void run() {
max = arr[first];
for (int i = first + 1; i <= last; i++) {
if (arr[i] > max) max = arr[i];
}
}
}
Main:
public class MainMax {
public static void main(String[] args) throws Exception {
int size = 100;
int workers = 10;
int[] arr = new int[size];
int max = 0;
for (int i = 0; i < size; i++) {
arr[i] = (int)(Math.random() * 100);
if (max < arr[i]) max = arr[i];
}
System.out.println("max=" + max);
int gsize = (arr.length - 1) / workers;
MaxTask[] tasks = new MaxTask[workers];
int first = 0;
int last;
for (int i = 0; i < workers; i++) {
last = first + gsize;
tasks[i] = new MaxTask(arr, first, last);
tasks[i].start();
first = last + 1;
}
int maxmax = tasks[0].getMax();
int temp;
for (int i = 1; i < workers; i++) {
temp = tasks[i].getMax();
if (temp > maxmax) maxmax = temp;
}
System.out.println("maxmax=" + maxmax);
}
}
I am trying to solve the problem using synchronized. I managed to get it working when using synchronized on both run and getMax. But I really don't understand why this solves the problem.
First, you must understand that the main class is also running on a thread. That thread is seperate from the threads you created for the function and is thus running in parallel to them. By that logic, int maxmax = tasks[0].getMax(); is running asynchronously and possibly before the loop is finished.
One possible solution would be to lock that part of the code and force the execution to wait before executing that line. Only release the lock after everyone in the loop is done. Synchronizing access to the run method only defeats the purpose of running multiple threads since you're forcing the whole thing to be sequential.
It is also not recommended to create a thread for every single element, since there's a tradeoff between number of threads and how much you're speeding up execution.
I'm trying to multiply three matrices using threads. I use a number of threads for a matrix multiplication and I should use another number of threads for multiply the result of the two matrices with the last matrices, and I would like to start the threads for the second multiplication as soon as they start having data from the first multiplication result. I'm a little stuck.
What I've tried:
public class Threads implements Runnable{
private String action;
private int range;
public Threads(String action, int range) {
this.action = action;
this.range = range +1;
}
public synchronized void run() {
int k;
int counter = 0;
int m_size = Program.m1.length;
int k_size =Program.m1[0].length;
int n_size = Program.m2[0].length;
int h_size = Program.m3[0].length;
for (int i=0; i<m_size; i++)
for (int j=0; j<n_size; j++) {
counter++;
if (counter % range == 0) {
int val1 = 0;
for (k = 0; k < k_size; k++) {
Program.result[i][j] += Program.m1[i][k] * Program.m2[k][j];
// int val1 =0;
for (int h=0; h<h_size; h++){
val1 += Program.result[i][h] * Program.m3[h][j];
}
}
Program.result_matrix[i][j] = val1; //here run error
}
}
}
public class Program {
private final static Random rand = new Random();
public static int[][] m1 = new int[][]{};
public static int[][] m2 = new int[][]{};
public static int[][] m3 = new int[][]{};
public static int[][] result = new int[][]{};
public static int[][] result_matrix = new int[][]{};
public static void generate(String action, int number_of_threads) throws InterruptedException {
List<Thread> all_threads = new ArrayList<>();
for (int th = 0; th < number_of_threads; th++) {
Thread t = new Thread(new Threads(action, th));
all_threads.add(t);
t.start();
}
for (Thread t : all_threads) {
t.join();
}
}
public static void main(String[] args) throws Exception {
{ //here i m reading the matrices
generate(action, number_of_threads);
print_result_matrix();
public static void print_result_matrix() {
for (int i = 0; i < result_matrix.length; i++) {
for (int j = 0; j < result_matrix[0].length; j++)
System.out.print(result_matrix[i][j] + " ");
System.out.println();
}
}
When I run this program I got an error after setting the matrices rows and columns and gives me error at line //look at code.
Anyway some ideas?I know that my code doesn't have a logic in run() method at the end but I really don't know how to achieve this.
Any ideas?
Stacktrace:
Exception in thread "Thread-0" Exception in thread "Thread-1 java.lang.ArrayIndexOutOfBoundsException: 0
at Threads.run(Threads.java:43)
at java.lang.Thread.run(Thread.java:745) java.lang.ArrayIndexOutOfBoundsException: 0
at Threads.run(Threads.java:43)
at java.lang.Thread.run(Thread.java:745)
You need to initialize result matrices' sizes:
public static int[][] result = new int[m1.length][m2[0].length];
public static int[][] result_matrix = new int[result.length][m3[0].length];
Of course, this should be done after m1, m2 and m3 are filled with data.
I'm trying to learn multi-threading but cant get the hang of it. I've an example here.
The idea is to use two threads to sort the two arrays a and b and use another thread to merge the sorted arrays to array c.
This is my code. I tried it with threads didnt work, so i've put up the code without the threads
public class Main {
public static void main(String[] args){
Random r = new Random(System.currentTimeMillis());
int n = r.nextInt(101) + 50;
int[] a = new int[n];
for(int i = 0; i < n; i++)
a[i] = r.nextInt(100);
n = r.nextInt(101) + 50;
int[] b = new int[n];
for(int i = 0; i < n; i++)
b[i] = r.nextInt(100);
SortThread t1 = new SortThread(a);
SortThread t2 = new SortThread(b);
MergeThread m = new MergeThread(t1.get(),t2.get());
System.out.println(Arrays.toString(m.get()));
}
}
public class SortThread {
int[] x;
public SortThread(int[] x){
this.x = x;
run();
}
public void run(){
sort(x);
}
private void sort(int[] x){
for(int i = 0; i < x.length ; i++){
int indexOfSmallest = findIndexOfSmallest(x, i);
int t = x[i];
x[i] = x[indexOfSmallest];
x[indexOfSmallest] = t;
}
}
private int findIndexOfSmallest(int[] a, int from){
int indexOfSmallest = from;
for(int i = from; i < a.length; i++)
if(a[i] < a[indexOfSmallest])
indexOfSmallest = i;
return indexOfSmallest;
}
public int[] get(){
return x;
}
}
public class MergeThread {
int[] a;
int[] b;
int[] c;
public MergeThread(int[] a, int[] b){
this.a = a;
this.b = b;
c = new int[a.length + b.length];
run();
}
public void run(){
merge();
}
private void merge(){
int aIndex = 0, bIndex = 0, cIndex = 0;
while(aIndex < a.length && bIndex < b.length)
if(a[aIndex] < b[bIndex])
c[cIndex++] = a[aIndex++];
else
c[cIndex++] = b[bIndex++];
while(aIndex < a.length)
c[cIndex++] = a[aIndex++];
while(bIndex < b.length)
c[cIndex++] = b[bIndex++];
}
public int[] get(){
return c;
}
}
A thread should implement the interface runnable and should override the method run.
Please Read Complete reference JAVA, it has many good examples.
Like i mentioned even if you extend thread/implement runnable, the thread you are creating has to be started by a start method, which should be overrided again.
public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } }
After this new can create a new instance of your thread and start it . In your case It should be
t1.start()
t2.start()
m.start()
I've been writing the following code for my OS course and I got some weird results. The code creates x threads and runs them concurrently in order to multiply two squared matrices. Every thread will multiply Number_of_rows/Number_of_threads rows of the input matrices.
When running it on a 1024X1024 matrices, with 1...8 threads, I get that the fastest multiplication happens when using only one thread. I would expect that a MacBook pro with i5 processor (2-cores) will utilize the two cores and that will yield faster results when using two threads.
Running time goes from about ~9.2 seconds using one thread, ~9.6 seconds to 27 seconds using 8.
Any idea why this is happening?
BTW, A few things about the code:
a. Assume that both matrices have identical dimensions and are square.
b. Assume that number of threads <= number of rows/columns.
public class MatrixMultThread implements Runnable {
final static int MATRIX_SIZE = 1024;
final static int MAX_THREADS = MATRIX_SIZE;
private float[][] a;
private float[][] b;
private float[][] res;
private int startIndex;
private int endIndex;
public MatrixMultThread(float[][] a, float[][]b, float[][] res, int startIndex, int endIndex) {
this.a = a;
this.b = b;
this.res = res;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
public void run() {
float value = 0;
for (int k = startIndex; k < endIndex; k++) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
value += a[k][j]*b[j][i];
}
res[k][i] = value;
value = 0;
}
}
}
public static float[][] mult(float[][] a, float[][] b, int threadCount){
// Get number of rows per each thread.
int rowsPerThread = (int) Math.ceil(MATRIX_SIZE / threadCount);
float[][] res = new float[MATRIX_SIZE][MATRIX_SIZE];
// Create thread array
Thread[] threadsArray = new Thread[threadCount];
int rowCounter = 0;
for (int i = 0; i < threadCount; i++) {
threadsArray[i] = new Thread(new MatrixMultThread(a,b,res,rowCounter, Math.max(rowCounter + rowsPerThread, MATRIX_SIZE)));
threadsArray[i].start();
rowCounter += rowsPerThread;
}
// Wait for all threads to end before finishing execution.
for (int i = 0; i < threadCount; i++) {
try {
threadsArray[i].join();
} catch (InterruptedException e) {
System.out.println("join failed");
}
}
return res;
}
public static void main(String args[]) {
// Create matrices and random generator
Random randomGenerator = new Random();
float[][] a = new float[MATRIX_SIZE][MATRIX_SIZE];
float[][] b = new float[MATRIX_SIZE][MATRIX_SIZE];
// Initialize two matrices with initial values from 1 to 10.
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
a[i][j] = randomGenerator.nextFloat() * randomGenerator.nextInt(100);
b[i][j] = randomGenerator.nextFloat() * randomGenerator.nextInt(100);
}
}
long startTime;
for (int i = 1; i <= 8; i++) {
startTime = System.currentTimeMillis();
mult(a,b,i);
System.out.println("Total running time is: " + (System.currentTimeMillis() - startTime) + " ms");
}
}
}
Firstly a bit of logging helps. I did logging for this and found out a bug in your logic.
Here is the log
Starting execution for thread count: 1
Start index: 0
End index: 1024
Starting execution: MatrixMultiplier: 0
Ending executionMatrixMultiplier: 0
Total running time is: 6593 ms
Starting execution for thread count: 2
Start index: 0
End index: 1024 <------ This is the problem area
Start index: 512
End index: 1024
Starting execution: MatrixMultiplier: 1
Starting execution: MatrixMultiplier: 0
Your first thread in all iterations is performing whole multiplication everytime. That's why you are not seeing results. Figure out the bug.
Trying to get a multi-threaded matrix multiplication to work in Java. It is given a (m x n) matrix, a (n x k) matrix and 't' threads to perform the operation on.
My program works when the matrices are square and t == n. When running with t < n, the other threads do not pick up the additional operations, and it returns a partially completed matrix. When the matrices are not square, the additional threads return array out of bounds errors and do not run. I would really appreciate any advice. Here are the relevant code snippets
Beginning threads. multipliers is an array of MatrixMultiplier, a class defined later.
Multiply multiply = new Multiply(cols_mat, rows_mat2);
for (int i = 0; i < threads; i++) {
multipliers[i] = new MatrixMultiplier(multiply);
}
for (int i = 0; i < threads; i++) {
my_threads[i] = new Thread(multipliers[i]);
}
for (int i = 0; i < threads; i++) {
my_threads[i].start();
}
for (int i = 0; i < threads; i++) {
my_threads[i].join();
}
Multiply class which defines the matrix multiplication
class Multiply extends MatrixMultiplication {
private int i;
private int j;
private int chance;
public Multiply(int i, int j) {
this.i = i;
this.j = j;
chance = 0;
}
public synchronized void multiplyMatrix() {
int sum = 0;
int a = 0;
for (a = 0; a < i; a++) {
sum = 0;
for (int b = 0; b < j; b++) {
sum = sum + mat[chance][b] * mat2[b][a];
}
result[chance][a] = sum;
}
if (chance >= i)
return;
chance++;
}
}
And the matrix multiplier
class MatrixMultiplier implements Runnable {
private final Multiply mul;
public MatrixMultiplier(Multiply mul) {
this.mul = mul;
}
#Override
public void run() {
mul.multiplyMatrix();
}
}
Where I personally think the issue lies is with if (chance >= i) return; but I have not found a way to incorporate a thread's column responsibilities with the program still working. Again, any advice pointing me in the right direction would be greatly appreciated.
There are several issues with your code.
The t threads assume that only t multiplications are required to produce your result matrix. This is not to be the case when m != k or t != m or t != k. The threads are worker threads that will only process your requests. I would consider making each MatrixMultiplier have access to the mxn, nxk, mxk matrices and a rolcolumn entries container.
class MatricMultiplier {
private double a[][], b[][], results[][];
private Queue<..> entries;
....
}
The run method will then use the entries container to calculate the sum for a given <row,column> entry of the resulting mxk matrix. The run method could become:
run() {
for (Entry entry = entries.poll(); entry != null; entry = entries.poll()) {
int row = entry.row;
int col = entry.col;
double sum = 0.0;
for (int i = 0; i < a[row].length; i++) {
sum += a[row][i] * b[i][col];
}
results[row][col] = sum;
}
}
There are three things to note here that is different than what you have.
you are not using a synchronization block
each entry is calculating the answer for a unique row/column of the result matrix
the Multiple class is not required any longer
You can then create t threads that process each entry in the entries container and will exit when the entries container is empty.
Note that the entries container should be one of the concurrent Queue containers available in the java.util.concurrent package.
The remaining task is how to create the rowcolumn entries container. Here is some code that you could use:
Queue<..> entries = new Concurrent...<..>();
int rowSize = a.length;
int colSize = b[0].length;
for (int row = 0; row < rowSize; row++) {
for (int col = 0; col < colSize; col++) {
entries.add(new RowColumnEntry(row, col));
}
}
Noting that the a and b are the m×n and n×k matrices.
Hope this helps.