I'm writing a demo program to explain how to regulate the concurrency of a crowd of threads in Java, but the result is not as I expected. This is the code:
package parcountSyncStat;
public class Parcount extends Thread {
private static int N=1000;
private static Integer x=0;
public static void main(String[] args) throws InterruptedException {
Thread[] t = new Thread[N];
int i;
for (i = N-1; i >= 0; i--) {
t[i]=new Parcount();
t[i].start();
}
for ( i=N-1; i>=0; i-- ) t[i].join();
System.out.println(x);
}
public void run() { synchronized(x) { x++; } }
}
In a nutshell, 1000 threads try to increment the same integer x. To preserve consistency, I encacsulate the increment in a synchronized block. The parent thread waits for all processes to finish, and then prints the final value of x, which should be 1000. But it isn't. My question is: why? I'm I wrong somewhere?
Note that I obtain the expected result by implementing a class that encapsulates the integer with a synchronized "Increment" method. But replacing the synchronized with a lock/unlock pair does not work either. I'm using Eclipse and did try both openjdk and oracle jdk, with similar results.
Thanks
x++ creates a new Integer object - so every time you run that statement the lock used becomes different. If you want one single lock for all you thread, create an ad hoc object:
private static final Object lock = new Object();
and synchronize on that lock.
Thanks to assylias: here is the complete code:
public class Parcount extends Thread {
private static int N=1000;
private static Integer x=0;
private static final Object lock = new Object();
public static void main(String[] args)
throws InterruptedException {
Thread[] t = new Thread[N];
int i;
for ( i=N-1; i>=0; i-- ) {
t[i]=new Parcount();
t[i].start();
}
for ( i=N-1; i>=0; i-- ) t[i].join();
System.out.println(x);
}
public void run() { synchronized(lock) { x++; } }
}
The following code uses the owner of your shared resource x, the class Example, as the instance to synchronize with. You may try changing your code like this:
public class Example extends Thread {
public static void main(String[] args) throws InterruptedException {
Thread[] t = new Thread[N];
for (int i = N - 1; i >= 0; i--) {
t[i] = new Example();
t[i].start();
}
for (int i = N - 1; i >= 0; i--) t[i].join();
System.out.println(x);
}
private static int N = 1000;
private static int x = 0;
#Override public void run() {
synchronized (Example.class) { x++; }
}
}
Related
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.
public class ThreadsDemo {
public static int n = 0;
private static final int NTHREADS = 300;
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
// try {
// Thread.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
n += 1;
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
}
Why the output is "n is: 300"? n isn't explicitly synchronized. And if I uncomment "Thread.sleep", the output is "n is: 299 or less".
I changed your code this way:
private static final int NTHREADS = 300;
private static AtomicInteger n = new AtomicInteger();
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
n.incrementAndGet();
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
You have to deal with racing-conditions. All the 300 threads are modifying n concurrently. For example: if two threads would have read and increment n concurrently than both increment n to the same value.
That was the reason why n wasn't always 300, you lost one increment in such a situation. And this situation could have occurred zero or many times.
I changed n from int to AtomicInteger which is thread safe. Now everything works as expected.
You better use AtomicInteger.
This question will help you with description and example: Practical uses for AtomicInteger
Static context need to have lock on the class and not on the Object. If you need a static variable to be synchronized and do not need it to be cached inside the thread locally you need to declare it as volatile.
public class ThreadsDemo {
public static int n = 0;
private static final int NTHREADS = 30;
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 1000; j++) // run a long time duration
n += 1;
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
}
output "n is: 29953"
I think the reason is, the threads run a short time duration, and the jvm don't make a context switch.
Java static field will be synchronized among threads?
No. You should make it volatile or synchronize all access to it, depending on your usage patterns.
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.
I had my code working (at least somewhat) and I must have changed something, because now it won't even launch. There's no shown errors within the code, but when I try to run it this is what appears:
Exception in thread "Thread-2" java.lang.NullPointerException
at azsystem3.Add.run(Main.java:57)
at java.lang.Thread.run(Thread.java:662)
and (Main.java:57) is this line: sum.s+=a[i];
How do I fix it?
Here's my relevant code:
package azsystem3;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Fill implements Runnable{
int []a;
static Random b = new Random();
int start;
int end;
public Fill(int[]a,int start,int end){
this.a=a;
this.start=start;
this.end=end;
}
public void run(){
for(int i=this.start;i<this.end;i++){
a[i]=b.nextInt(100);
}
}
}
class value{
int s;
}
class Add implements Runnable{
value sum;
Lock L ;
int[]a;
int start;
int end;
//public long sum=0;
public Add(int[]a,int start, int end,Lock L,value s){
this.L=L;
this.start=start;
this.end=end;
sum=s;
}
public void run(){
int i;
for( i=start;i<end;i++)
L.lock();
sum.s+=a[i];
L.unlock();
}
}
class main {
public static void main(String[] args) {
value sum=new value();
Lock Lock=new ReentrantLock();
int[] array = new int[100000];
Scanner sc=new Scanner (System.in);
System.out.println ("Enter number : ");
int n = sc.nextInt();
int tmp = 100000 / n;
Thread[] t = new Thread[n];
for (int i = 0; i < n; i++) {
t[i] = new Thread(new Fill(array, (i) * tmp, (i + 1) * tmp));
t[i].start();
}
for (int i = 0; i < n; i++) {
try {
t[i].join();
} catch (InterruptedException exception) {
}
}
Thread[] t1 = new Thread[n];
Add[] add = new Add[n];
long start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
add[i] = new Add(array, (i) * tmp, (i + 1) * tmp,Lock,sum);
t1[i] = new Thread(add[i]);
t1[i].start();
}
for (int i = 0; i < n; i++) {
try {
t1[i].join();
} catch (InterruptedException exception) {
}
}
long end = System.currentTimeMillis();
System.out.println("sum : " + sum);
System.out.println("time : " + (end - start) + "ms");
}
}
Any suggestions?
Thread-safety does not only requires locking on run()-method in your code, but you should also make your private members of class Add, especially the sum member, final. Otherwise a Thread might see a not fully initialized object of type value where the sum-member is still null.
And note: Please try to follow standard Java code conventions for better readability.
Another observation, this code
for( i=start;i<end;i++) // missing opening bracket {
L.lock();
sum.s+=a[i];
L.unlock(); // missing closing bracket }
is equivalent to:
for( i=start;i<end;i++) {
L.lock();
}
sum.s+=a[i];
L.unlock();
I have no trust in any thread-safety here because of improper handling of brackets and therefore locking.
While it looks like a thread-safety issue, the reason for the NullPointerException is quite simple:
In the constructor for the Add class you forgot to assign the int array instance variable a, i.e. a simple this.a=a; is missing.
That’s a reason why you should declare every instance variable as final whenever possible. Then the compiler will tell you about every missing value assignment.
Of course, you will have to fix the missing braces in the Add.run() method as well as otherwise you will get a dead-lock. In your case only the first thread threw a NullPointerException while all other threads were waiting forever.
I am reading "Java Concurrency in practice" and looking at the example code on page 51.
This states that if a thread has references to a shared object then other threads may be able to access that object before the constructor has finished executing.
I have tried to put this into practice and so I wrote this code thinking that if I ran it enough times a RuntimeException("World is f*cked") would occur. But it isn't doing.
Is this a case of the Java spec not guaranting something but my particular implementation of java guaranteeing it for me? (java version: 1.5.0 on Ubuntu) Or have I misread something in the book?
Code: (I expect an exception but it is never thrown)
public class Threads {
private Widgit w;
public static void main(String[] s) throws Exception {
while(true){
Threads t = new Threads();
t.runThreads();
}
}
private void runThreads() throws Exception{
new Checker().start();
w = new Widgit((int)(Math.random() * 100) + 1);
}
private class Checker extends Thread{
private static final int LOOP_TIMES = 1000;
public void run() {
int count = 0;
for(int i = 0; i < LOOP_TIMES; i++){
try {
w.checkMe();
count++;
} catch(NullPointerException npe){
//ignore
}
}
System.out.println("checked: "+count+" times out of "+LOOP_TIMES);
}
}
private static class Widgit{
private int n;
private int n2;
Widgit(int n) throws InterruptedException{
this.n = n;
Thread.sleep(2);
this.n2 = n;
}
void checkMe(){
if (n != n2) {
throw new RuntimeException("World is f*cked");
}
}
}
}
You don't publish the reference until after the constructor has finished, change Widgit like this:
private class Widgit{ // NOTE: Not class is not static anymore
private int n;
private int n2;
Widgit(int n) throws InterruptedException{
this.n = n;
w = this; // publish reference
Thread.sleep(2);
this.n2 = n;
}
void checkMe(){
if (n != n2) {
throw new RuntimeException("World is f*cked");
}
}
Should now throw.
Edit: You should also declare the Widgit field as volatile:
private volatile Widgit w;
Well, you need to understand the issues a little more. It isn't really a case of anything being or not being "guaranteed." With concurrency problems, nothing is really guaranteed unless you really do specific things to force the problem to happen. You're just relying on the hope that enough runs should produce, which is not the case. These kinds of problems are hard to predict, which is why concurrency is a hard problem. You could try doing more work in your functions, but I assure you these are real problems that the runtime is not going to save you from.
Before sleeping, start a new thread which prints the value of n2. You will see the second thread can access the object before the constructor has finished.
The following example demonstrates this on the Sun JVM.
/* The following prints
Incomplete initialisation of A{n=1, n2=0}
After initialisation A{n=1, n2=2}
*/
public class A {
final int n;
final int n2;
public A() throws InterruptedException {
n = 1;
new Thread(new Runnable() {
public void run() {
System.out.println("Incomplete initialisation of " + A.this);
}
}).start();
Thread.sleep(200);
this.n2 = 2;
}
#Override
public String toString() {
return "A{" + "n=" + n + ", n2=" + n2 + '}';
}
public static void main(String... args) throws InterruptedException {
System.out.println("After initialisation " + new A());
}
}
This will never throw a RunTimeException because your Widgit instance variable w remains null until the constructor code has executed. While your main thread is sleeping in the Widgit constructor, your Checker instance is hitting NullPointerException constantly as the w variable is still null. When your main thread finishes construction, the two int variables in Widgit are equal.