class TestSync {
public static void main(String[] args) throws InterruptedException {
Counter counter1 = new Counter();
Counter counter2 = new Counter();
Counter counter3 = new Counter();
Counter counter4 = new Counter();
counter1.start();
counter2.start();
counter3.start();
counter4.start();
counter1.join();
counter2.join();
counter3.join();
counter4.join();
for (int i = 1; i <= 100; i++) {
if (values[i] > 1) {
System.out.println(String.format("%d was visited %d times", i, values[i]));
} else if (values[i] == 0) {
System.out.println(String.format("%d wasn't visited", i));
}
}
}
public static Integer count = 0;
public static int[] values = new int[105];
static {
for (int i = 0; i < 105; i++) {
values[i] = 0;
}
}
public static void incrementCount() {
count++;
}
public static int getCount() {
return count;
}
public static class Counter extends Thread {
#Override
public void run() {
do {
synchronized (count) {
incrementCount();
values[getCount()]++;
}
} while (getCount() < 100);
}
}
}
That is a code from one online course. My task is to make this code visit each element of array only once (only for elements from 1 to 100). So I have added simple synchronized block to run method. In case of using values inside of that statement everything works. But with count it doesn't want to work.
What the difference? Both of this objects are static fields inside of the same class. Also I have tried to make count volatile but it hasn't helped me.
PS: a lot of elements are visited 2 times and some of them even 3 times. In case of using values in synchronized all elements are visited only once!!!
Integer is immutable. The moment you call increment method, You get a new object and reference of count variable gets changed and hence leads to an issue.
Related
To understand the concept of threads better, we are supposed to use a Number object that can be increased, decreased, squared and rooted via it's methods. It's only attribute is a double number (initialized as number=1).
So if i instantiate the Number object and call increment(), decrement(), square() and root() 100000000 times to that number object, the number attribute is 1 again (as expected).
Now the problem is that we are supposed to instantiate two thread objects, one calling the increase/decrease 100000000 times and the other one calling square/root 100000000 times.
According to our teacher the result would be inconsistency, i.E getting 0 instead of 1 as the result, but in my program it just gives me infinity or 1 depending on wether or not i am using synchronized() in the Thread class.
public class Calculation {
public static void main(String[] args) throws InterruptedException {
Number num = new Number();
Number num1 = new Number();
for (int i = 0; i < 100000000; i++) {
num.increment();
}
for (int i = 0; i < 100000000; i++) {
num.decrement();
}
for (int i = 0; i < 100000000; i++) {
num.square();
}
for (int i = 0; i < 100000000; i++) {
num.root();
}
System.out.println(num.getNumber());
CalcThread t1 = new CalcThread(num1, true);
CalcThread t2 = new CalcThread(num1, false);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(num1.getNumber());
}
}
public class CalcThread extends Thread {
public Number num;
public boolean decision;
public CalcThread(Number num, boolean decision) {
this.num = num;
this.decision = decision;
}
#Override
public void run() {
synchronized(num) {
if (this.decision) {
for (int i = 0; i < 100000000; i++) {
num.square();
}
for (int i = 0; i < 100000000; i++) {
num.root();
}
} else {
for (int i = 0; i < 100000000; i++) {
num.increment();
}
for (int i = 0; i < 100000000; i++) {
num.decrement();
}
}
}
}
}
public class Number {
double number;
public Number() {
this.number = 1;
}
public void increment() {
this.number++;
}
public void decrement() {
this.number--;
}
public void square() {
this.number = this.number * this.number;
}
public void root() {
this.number = Math.sqrt(this.number);
}
public double getNumber() {
return number;
}
public void setNumber(double number) {
this.number = number;
}
}
Getting infinity when leaving synchronized out makes sense because it is increasing while squaring the number at the same time, so the number will soon be too large to fit the double type size right?
How do i get the inconsistency my teacher was talking about?
Thank you for your help in advance.
I have created a function "m7" in my class but this function is always returning value getting multiplied by 2.
If I am running this function in "psvm" it is printing the right value.
In my Alice class, the method m7() is returning 10 which is incorrect but if I am running this method in psvm then it is returning 5 which is correct.
package com.math.functions;
import java.util.*;
public class Alice {
Integer[] rank= new Integer[7];
Integer n=65;
int count=0;
public Alice() {
rank[0]=100;
rank[1]=100;
rank[2]=90;
rank[3]=80;
rank[4]=75;
rank[5]=60;
rank[6]=n;
//rank[6]=20;
//rank[7]=10;
//rank[8]=n;
Arrays.sort(rank, Collections.reverseOrder());
}
public void print() {
for (Integer a : rank) {
System.out.println(a);
}
}
public int m7() {
for (int i = 0; i < rank.length; i++) {
if (rank[i] == n) {
break;
}
count++;
}
return count;
}
public void res(){
int s = m7();
System.out.println("this is the value of s here :"+s);
Set<Integer> hash_Set = new HashSet<>();
for(int i=0;i<=s/2;i++){
System.out.println("hii");
hash_Set.add(rank[i]);
}
for(Integer o:hash_Set){
System.out.println(o);
System.out.println("rank:"+hash_Set.size());
}
}
public static void main(String[] args) {
Alice a=new Alice();
a.print();
System.out.println("this is: "+a.m7());
a.res();
}
}
You are reusing the value of count from the previous time you run it.
Don't declare count as a member variable, make it a local variable.
public int m7() {
int count = 0; // HERE
for (int i = 0; i < rank.length; i++) {
if (rank[i] == n) {
break;
}
count++;
}
return count;
}
I am trying to learn using the monitor by creating an array of int, length being 100. It is filled with 0 and I try to make 4 threads that would swap the 0 with numbers from top and bottom of the array.
For some reason only 2 out of 4 threads (and it seems that it is random) executes. I have tried to change it by creating an array and increasing the respected member of the array by 1 for 100k iterations and it seems that every thread did it for about 25k times so I suppose the problem is with the part where I tried to swap 0 in the array.
Here is my code:
class addFromBottom implements Runnable{
int number;
public addFromBottom(int number){
this.number=number;
}
#Override
public void run() {
for (int i = number-1; i <100 ; i+=2) {
if (MainClass.testMonitor.elementsNotChanged>0)
MainClass.testMonitor.addNumberFromBottom(number,i);
else
break;
}/*
while (MainClass.testMonitor.testCounter>0)
MainClass.testMonitor.testCounter(number);*/
}
}
class addFromTop implements Runnable{
int number;
public addFromTop(int number){
this.number=number;
}
#Override
public void run() {
for (int i = 95+number; i >=0 ; i-=2) {
if (MainClass.testMonitor.elementsNotChanged>0){
MainClass.testMonitor.addNumberFromBottom(number,i);
}
else {
break;
}
}
/*while (MainClass.testMonitor.testCounter>0)
MainClass.testMonitor.testCounter(number);*/
}
}
class monitor
{
int elementsNotChanged = 100;
int[] array;
int testCounter = 100000;
int[] testArray = new int[]{0,0,0,0};
public monitor(){
array=new int[100];
for (int i = 0; i < 100; i++) {
array[i]=0;
}
}
synchronized void addNumberFromBottom(int number,int index){
if (elementsNotChanged<=0) {
return;
}
if (array[index]==0){
array[index]=number;
return;
}
}
//for testing if the threads are working seperatly
synchronized void testCounter(int number) {
if (testCounter<=0)
return;
testArray[number - 1]++;
testCounter--;
notifyAll();
}
}
class MainClass {
public static int a=0;
public static volatile monitor testMonitor;
public static void main(String[] args) throws InterruptedException {
testMonitor = new monitor();
Thread thread = new Thread(new addFromBottom(1));
Thread thread2 = new Thread(new addFromBottom(2));
Thread thread3 = new Thread(new addFromTop(3));
Thread thread4 = new Thread(new addFromTop(4));
thread.start();
thread2.start();
thread3.start();
thread4.start();
thread.join();
thread2.join();
thread3.join();
thread4.join();
System.out.println();
System.out.println();
System.out.println();
System.out.println("value: i");
for (int i = 0; i < 100; i++) {
System.out.println(testMonitor.array[i]+" "+i);
}
//for testing with the array of 4 elements if all threads are doing their work
int sum=0;
for (int i = 0; i <4 ; i++) {
//System.out.println(testMonitor.testArray[i]);
sum+=testMonitor.testArray[i];
}
// System.out.println(sum);
}
}
I read now Thinking in Java, chapter about atomicity and visibility. There is an example I don't understand.
public class SerialNumberGenerator {
private static volatile int serialNumber = 0;
public static int nextSerialNumber() {
return serialNumber++;
}
}
class CircularSet {
private int[] array;
private int len;
private int index = 0;
public CircularSet(int size) {
array = new int[size];
len = size;
for (int i = 0; i < size; i++) {
array[i] = -1;
}
}
synchronized void add(int i) {
array[index] = i;
index = ++index % len;
}
synchronized boolean contains(int val) {
for (int i = 0; i < len; i++) {
if (array[i] == val)
return true;
}
return false;
}
}
public class SerialNumberChecker {
private static final int SIZE = 10;
private static CircularSet serials = new CircularSet(1000);
private static ExecutorService exec = Executors.newCachedThreadPool();
static class SerialChecker implements Runnable {
#Override
public void run() {
while (true) {
int serial = SerialNumberGenerator.nextSerialNumber();
if (serials.contains(serial)) {
System.out.println("Duplicate: " + serial);
System.exit(0);
}
serials.add(serial);
}
}
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < SIZE; i++) {
exec.execute(new SerialChecker());
}
}
}
example output:
Duplicate: 228
I don't understand how is it possible. Even method nextSerialNumber() is not synchronized and all thread generate different values each thread has own value of serial and each are different. So how is it possible to find duplicate. I cannot imagine of threads execution.
This example shows the post-increment operator is not atomic and not thread-safe.
What happens in this code is:
many (up to 100) threads are started, each executing the same code
in an infinite loop:
an unsynchronized method nextSerialNumber is called, which returns the result of the post-increment operator called on a static variable
a synchronized method contains is called, which checks if the returned value exists in the underlying collection
if yes, the program is terminated
if not, the value is added to the underlying collection
If the post-increment operation was thread-safe then the program would never print "Duplicate" and would never terminate,
since every thread would be getting a different serial number value. This is not the case as two threads
might get exactly the same serial number value.
I am trying to calculate all the primes up to an arbitrary number by computing them in parallel. I'm aware that isPrime() can be improved from what it is now, but the main problem is that I can't synchronize access to the ArrayList that is storing the results. I've instantiated a dummy object "m" to serve as a monitor and control access to the array. Obviously I've made a mistake in reasoning somewhere because I get a java.util.ConcurrentModificationException every time. NB: gist
EDIT: updated to show completion after suggestions.
import java.util.ArrayList;
public class Main {
static final int MAX = 100000000;
static final int THREADS = Runtime.getRuntime().availableProcessors();
static final int ARRINITSIZE = 100000;
static ArrayList<Integer> primes = new ArrayList<Integer>(ARRINITSIZE);
public static void main(String[] args) {
Thread[] t = new Thread[THREADS];
PrimeRun.m = new Monitor();
for (int i=0; i<THREADS; i++) {
t[i] = new Thread(new PrimeRun(i) );
t[i].start();
}
// wait for threads to finish
for (int i=0; i<THREADS; i++)
t[i].join();
// NOTE: primes will be out of order because of random thread scheduling
for (int n : primes)
System.out.print("" + n + " ");
System.out.println();
}
static boolean isPrime(int n) {
if (n == 2 || n == 3 || n == 5) return true;
if (n <= 1 || (n&1) == 0) return false;
for (int i = 3; i*i <= n; i += 2)
if (n % i == 0) return false;
return true;
}
synchronized static void addPrime(int n) {
primes.add(n);
}
}
class PrimeRun implements Runnable {
public static Monitor m;
final int ID;
public PrimeRun(int i) {
ID = i;
}
public void run() {
for(int i=0; i < Main.MAX; i++) {
if(i % Main.THREADS == ID)
if(Main.isPrime(i))
m.addPrime(i);
}
}
}
class Monitor {
public synchronized void addPrime(int n) {
Main.addPrime(n);
}
}
I've included my ant script for convenience :)
<project default="cmp">
<target name="cmp"><javac srcdir="." debug="true"/></target>
<target name="run" depends="cmp"><java classname="Main" classpath="."/></target>
<target name="cln"><delete><fileset dir="." includes="*.class"/></delete></target>
</project>
How about declaring primes as
static List<Integer> primes = Collections.synchronizedList(new ArrayList<Integer>(ARRINITSIZE));
And you should be able to get rid of the Monitor and the synchronized blocks... Oh and you will have to wait till the threads that calculates primes to finish before starting to print values from primes list
Edit
Here is the modified program where it just waits for the threads to finish
import java.util.ArrayList;
import java.util.List;
public class Main {
static final int MAX = 1000;
static final int THREADS = Runtime.getRuntime().availableProcessors();
static final int ARRINITSIZE = 100000;
static ArrayList<Integer> primes = new ArrayList<Integer>(ARRINITSIZE);
public static void main(String[] args) {
PrimeRun.m = new Monitor();
List<Thread> thread = new ArrayList<Thread>();
for (int i=0; i<THREADS; i++){
Thread t = new Thread(new PrimeRun(i));
t.start();
thread.add(t);
}
for (Thread t : thread) {
if (t.isAlive()){
try {
t.join();
} catch (InterruptedException e) {
}
}
}
for (int n : primes)
System.out.print("" + n + " ");
}
static boolean isPrime(int n) {
if (n <= 1 || (n&1) == 0) return false;
if (n == 2 || n == 3 || n == 5) return true;
for (int i = 3; n*n <= i; i += 2)
if (n % i == 0) return false;
return true;
}
synchronized static void addPrime(int n) {
primes.add(n);
}
}
class PrimeRun implements Runnable {
public static Monitor m;
final int ID;
public PrimeRun(int i) {
ID = i;
}
public void run() {
for(int i=0; i < Main.MAX; i++) {
if(i % Main.THREADS == ID)
if(Main.isPrime(i))
m.addPrime(i);
}
}
}
class Monitor {
public synchronized void addPrime(int n) {
Main.addPrime(n);
}
}
You get ConcurrentModificationException because you are iterating over array while adding to it. It has nothing to do with multiple threads and will happen even in a single thread. But in your specific case it happens because threads are still adding primes when you start iterating over the list. To prevent that you must wait for all threads to finish before printing. To do it you can iterate array of threads and call join() on each one of them. Or you can use CountdownLatch.
List can be made synchronized via Collections.synchronizedList() as suggested in the other answer.
Reason fro ConcurrentModificationException is not bad synchronization. The reason is that you are modifying list during iteration on it.
The only iteration I found in your code is
for (int n : primes)
System.out.print("" + n + " ");
Here is what happens.
You are running several threads that do their job and add elements to collection. The code that runs threads is immediately following by code that iterates over list and prints its elements. So the iteration and your working threads are running simultaneously.
To fix this you should wait until all your working threads have finished and then print. Indeed you want to print the results only when all calculations have been finished. Check out method Thread.join() to implement this.
And obviously do what #maneesh recommended you, i.e. use Collections.synchronizedList() instead of your manual synchronization.