when I was reading about different ways of defining threads in Java, I can't able to synchronize Thread as a nested class. This is the code.
class OuterClass {
int count = 0;
InnerClass in[];
OuterClass() {
in = new InnerClass[4];
for (int i = 0; i < 4; i++) {
in[i] = new InnerClass();
}
}
public void startFun() throws Exception{
for (int i = 0; i < 4; i++) {
in[i].start();
}
for (int i = 0; i < 4; i++)
in[i].join();
}
public static void main(String[] agrs) throws Exception {
OuterClass oc = new OuterClass();
oc.startFun();
}
class InnerClass extends Thread {
public synchronized void run() {
count ++;
System.out.println(count);
}
}}
How to synchronize count variable in this program by using thread as a nested class? Because I used this model in my project. Output for the above program was:
output:
1
4
3
2
How to synchronize and get the output as:
1
2
3
4
You have 4 different objects (and 4 different monitors for locking) for synchronization (InnerClass1, InnerClass2 etc). For synchronization of all your threads, you should use one object (one monitor) for example:
class OuterClass {
Object ob = new Object();
volatile int count = 0;
InnerClass in[];
OuterClass() {
in = new InnerClass[4];
for (int i = 0; i < 4; i++) {
in[i] = new InnerClass();
}
}
public void startFun() throws Exception{
for (int i = 0; i < 4; i++) {
in[i].start();
}
for (int i = 0; i < 4; i++)
in[i].join();
}
public static void main(String[] agrs) throws Exception {
OuterClass oc = new OuterClass();
oc.startFun();
}
class InnerClass extends Thread {
public void run() {
synchronized (ob){
count ++;
System.out.println(count);
}
}
}}
also, your shared field should be volatile.
Related
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'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++; }
}
}
In Java, there are 3 threads that want to access (read-only) an immutable hashmap to do something. Is SynchronizedMap class below the fastest solution for that purpose? If not, then what would be faster to use?
import com.carrotsearch.hppc.IntObjectMap;
import com.carrotsearch.hppc.IntObjectOpenHashMap;
public class abc {
public static void main(String[] args) {
final IntObjectMap<int[]> map = new IntObjectOpenHashMap<int[]>();
for (int i = 0; i < 4; i++) {
map.put(i, new int[] {1, 2, 3, 4, 5});
}
Thread[] threads = new Thread[3];
class SynchronizedMap {
private final Object syncObject = new Object();
public final int[] read(int i) {
final int[] value;
synchronized (syncObject) {
// code that reads-only immutable map object
value = map.get(i);
}
return value;
}
}
final SynchronizedMap syncMap = new SynchronizedMap();
class AccessMap implements Runnable {
private int id;
AccessMap(int index) { id = index; }
public void run() {
// code that reads-only immutable map object like this:
for (int i = 0; i < 4; i++) {
final int[] array = syncMap.read(i);
for (int j = 0; j < array.length; j++)
System.out.println(id + ": " + array[j] + " ");
}
}
}
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new AccessMap(i) {});
threads[i].start();
}
for (int i = 0; i < threads.length; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Is SynchronizedMap class below the fastest solution for that purpose?
No. If the HashMap is truly immutable/read-only then a volatile Map<...> is the way to go.
volatile IntObjectMap<int[]> readOnlyMap = new IntObjectOpenHashMap<int[]>();
If you are starting your threads after your map is built then you don't even need the volatile. The only time you would need the volatile is if you are swapping in a new map that is being accessed by currently running threads.
final IntObjectMap<int[]> readOnlyMap = new IntObjectOpenHashMap<int[]>();
I am trying to learn multithreading concepts in Java. I am stuck with error during execution of my code snippet.
My code snippet:
class ThreadDemo {
public static void main(String args[]) {
try{
int [] arr = new int[10] ;
for(int i = 0 ; i < 10 ; i++)
arr[i] = i ;
for(int c =0 ; c < 2 ; c++){
for(int i = 0 ; i < 3 ; i++) //I want to run it on one thread
System.out.println(arr[i]);
for(int j = 0 ; j < 5 ; j++) //I want to run it on another thread
System.out.println(arr[j]);
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
Now, to solve this I have tried,
class ThreadDemo {
public static void main(String args[]) {
try{
int [] arr = new int[10] ;
for(int i = 0 ; i < 10 ; i++)
arr[i] = i ;
for(int c =0 ; c < 2 ; c++){
Thread thread1 = new Thread () {
public void run () {
for(int i = 0 ; i < 3 ; i++) //I want to run it on one thread
System.out.println(arr[i]);}
};
Thread thread2 = new Thread () {
public void run () {
for(int j = 0 ; j < 5 ; j++) //I want to run it on one thread
System.out.println(arr[j]);}
};
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
But gives error. Can anyone help me how to solve this ?
In
for (int c = 0; c < 2; c++) {
Thread thread1 = new Thread() {//<- here
you are creating anonymous inner class that extends Thread class. You must know, that anonymous inner classes have access only to final local variables of method that they are created so if you want to gain access to int [] arr you must make it final like
final int[] arr = new int[10];
Also you created threads but you didn't start them. To do that invoke their start() method like thread1.start().
If you don't want to declare local variables of method as final you should consider creating threads not as anonymous inner classes but as separate classes for example
class MyThread extends Thread {
int[] array;
int iterations;
public MyThread(int[] arr, int i) {
array=arr;
iterations = i;
}
#Override
public void run() {
for (int i = 0; i < iterations; i++)
System.out.println(array[i]);
}
}
class ThreadDemo {
public static void main(String args[]) {
try {
int[] arr = new int[10];
for (int i = 0; i < 10; i++)
arr[i] = i;
for (int c = 0; c < 2; c++) {
MyThread thread1 = new MyThread(arr, 3);
MyThread thread2 = new MyThread(arr, 5);
thread1.start();
thread2.start();
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
FYI: Extending Thread is not the best idea if you're not actually providing any additional logic to it. It's best to use a Runnable and pass it to the threads constructor.
Thread t = new Thread(new Runnable() {
public void run() {
}
});
t.start();
Aside from that, as someone else noted, any variables directly in an anonymous class need to be declared as final.