What I am trying to do involves keeping track of a variable while it prints an array out. However, what makes it confusing is that it is Asynchronous.
This is similar to what I have now.
public static int variable = 0;
public void print()
{
System.out.println(array[variable]);
variable ++;
}
Then another class with an ExecutorService and CompletionService that calls the print() method asynchronously which runs around 40 jobs with 4 threads (in my example its 11 jobs).
The problem (how I see it) is that since it is running asynchronously, 4 threads have the same value of variable or it skips some values because 2 threads finished at the same time therefore it incremented by 2.
I printed out the variable values and here are some results:
0 1 2 2 2 2 6 6 6 9 10
0 1 2 2 4 4 6 7 8 9 10
0 1 1 1 1 5 6 7 8 8 8
Declare the method print() synchronized.
Or declare the variable variable as AtomicInteger instead of int.
You could create a new class that handles printing:
public class SyncPrinter {
public static int variable = 0;
public static synchronized void print()
{
System.out.println(array[variable]);
variable ++;
}
}
Then call it as SyncPrinter.print()
Related
I have 3 class like this:
Source.java
public class Source extends Thread{
private int x= 0;
public void increment(int id){
x++;
System.out.println(id+" "+x);
}
}
Task.java
public class Task extends Thread{
private Source source;
private int id;
public Task(Source source, int id){
this.source=source;
this.id=id;
}
public void run(){
for (int i=0;i<100;i++){
try{Thread.sleep(1000);}catch(InterruptedException e){}
source.inc(id);
}
}
}
Main.java
public class Main{
public static void main(String[] args) throws IOException{
Source source = new Source();
Task t1=new Task(source,1);
Task t2=new Task(source,2);
t1.start();
t2.start();
}
}
I want when the x of the class Source will be equal to 4 only one task continues to increment x until x is equal to 8, we return to normal.
The result will look like this:
1 1
2 2
1 3
2 4
1 5
1 6
1 7
1 8
1 9
1 10
2 11
1 12
2 13
...
How do I modify the code to achieve the desired result?
Basically you have two threads that modify the same variable x. There is no garantee about the order of execution.
You should synchronize.
With your current implementation you may face a problem (The race condition problem): Race condition example
Something like this is an scenario that most likely is going to happen to you:
....
1 3
2 4
2 5
1 6
1 7
2 7
1 8
2 9
1 10
2 10
...
As you can see the thread 2 (source 2) tries to increment the variable x when the variable has been already incremented but the value it has to increment is the old one.
x = 0
Thread 1 reads the variable x (0)
Thread 2 reads the variable x (0)
Thread 1 increments variable x + 1 (0 + 1) = 1
Thread 2 increments variable x + 1 (0 + 1) = 1
In order to solve this you need to synchronize your variable, an AtomicInteger would be enough. + I don't think you need the extends Thread on your Source class, you can get rid of it
I am learning Threads synchronization in java and I have the following code :
class abs{
int x=0;
public void increment(){
for(int i =0 ; i<10 ; i++) {
//System.out.println(Thread.currentThread().getId());
x++;
System.out.println(x);
}
}
}
class thread_creation extends Thread{
abs t;
thread_creation(abs x){
t=x;
}
public void run() {
t.increment();
}
}
public class Test_sync {
public static void main(String[] args) {
abs ob = new abs();
thread_creation t1 = new thread_creation(ob);
thread_creation t2 = new thread_creation(ob);
t1.start();
t2.start();
}
}
When I run the code , I get the following output :
2
3
4
5
6
7
8
9
10
11
2
12
13
14
15
16
17
18
19
20
I have many questions regarding this output :
Why the output didn't start with 1 ? Initially x= 0 , so when the first thread increments and output x , then we should see 1 in the output ?
Why the output has value of 2 twice ?
I am very confused , so someone please explain why we got this output ?
Because the threads use a single variable to count.
A x+=1 (1)
B x+=1 (2)
A starts print (2), and goes to sleep
B prints 2
B keeps working, incrementing x, printing 3 to 11
B goes to sleep
A finishes the print of "2" it started a while back
Clarification of followup questions:
x is owned by the object ob of class abs there is only one which is shared across threads.
i is owned by the function public void increment() and there are two independent calls of it.
As to the behaviour of sleeping on printing... That's pretty much the whole point of threads. print takes forever from a cpu point of view and there are exclusive assets (there is only one console) involved
Not a full answer, but responding to a comment:
Why both threads don't share the loop counter variable i?...
That's because i is a local variable within the increment() method. Each call to increment() gets its own distinct i, which is created when the method is called, and which lives only until the method returns.
...although they share the variable x ?
Your x on the other hand is a member variable (a.k.a., a field) of the abs class. Each instance of the abs class gets its own distinct x, and that x lives as long as the instance lives. Your main() method creates just one instance of abs, and gives it to both threads.
What sets the two variables apart is where they are declared. i is declared inside the increment() method body. That's what makes it local. x is declared outside of any method, but inside the declaration of class abs {...}. That's what makes it an instance variable.*
* There are also static variables that can be declared inside a class, but I won't go in to that here.
I have an example like that:
public class MainApp {
private volatile static int MY_INT = 0;
public static void main(String[] args) {
new Thread1().start();
new Thread2().start();
}
static class Thread1 extends Thread {
#Override
public void run() {
while(true) {
MY_INT++;
System.out.println("1 : " + MY_INT);
}
}
}
static class Thread2 extends Thread{
#Override
public void run() {
while(true) {
MY_INT++;
System.out.println("2 : " + MY_INT);
}
}
}
}
And the output is:
1 : 1
2 : 2
1 : 3
2 : 4
1 : 5
1 : 7
1 : 8
1 : 9
1 : 10
2 : 6
1 : 11
1 : 13
I don't understand why after printing 1:10 and the next line is 2:6. Can anyone explain the result? Thanks in advance
There are several issues here:
threads may not run in parallel. They run in time slices (default: 15.6 ms on a PC; 64 ticks per second, see timer resolution (Microsoft)). This is why you don't see 1:x and 2:x one after another, but several 1:x after each other.
using volatile does not help with synchronization. You need real synchronization objects such as AtomicInteger or the synchronized keyword. Therefore you may see skipped numbers (not the case in your output, but it may occur). You need the synchronization around both, the ++ and the println() if you want to see unique numbers
Console output is buffered and synchronized, because you don't want 2 println statements to mix the output on one line
The PrintStream in System.out and the volatile field MY_INT are independently synchronized, so the following can happen:
Thread 1 Thread 2
read MY_INT = 4
write MY_INT = 5
read MY_INT = 5
read MY_INT = 5
write MY_INT = 6
read MY_INT = 6
println 5
read MY_INT = 6
write MY_INT = 7
read MY_INT = 7
println 7
...
println 6
That is, because the volatile field and the PrintStream returned by System.out are independently synchronized, printing may occur in non-ascending order.
The following could also happen:
Thread 1 Thread 2
read MY_INT = 1
read MY_INT = 1
write MY_INT = 2
write MY_INT = 2
read MY_INT = 2
println 2
read MY_INT = 2
println 2
because ++MY_INT is actually compiled into a read, a computation, and a write. Since volatile reads and writes are separate synchronization actions, other threads may act in between, and mess the counter up.
If you want ascending numbers being printed by separate threads, the easiest way is:
void run() {
while (true) {
synchronized (lock) {
MY_INT++;
System.out.println("1 : " + MY_INT);
}
}
}
where lock is an object shared by all threads accessing MY_INT.
public class Test implements Runnable {
static int i;
public void run() {
System.out.println(i);
}
public static void main(String[] args) {
Test t=new Test();
for(i=0;i<=5;i++){
Thread t1=new Thread(t);
t1.start();
System.out.println("The main method:"+i);
}
}
}
the answer i get is :-
The main method:0
0
The main method:1
2
The main method:2
The main method:3
The main method:4
5
The main method:5
6
6
6
EDIT : now I see that i is a static variable and is not declared in the loop. The reason it reaches 6 is that it is incremented until the loop's condition i <= 5 is no longer true, which happens when i reaches 6.
That's because of the i<=5. The 0 being included, i<5 iterates 5 times (starting from 0 and finishing at 4). If you add = you'll "force" the code to stop at 5, iterating 5 + 1 times.
This kind of error is called off-by-one and while it is a frequent error when you start programming it can cause to disastrous bug (see for example this famous bug in OpenSSL)
All threads share a single static int i;
The loop in main starts threads while i is (still!) 0, 1, 2, 3, 4, 5, but they will execute with some delay. Meanwhile, the main loop advances, and you see some later state of i.
Note that some values are missing, others are duplicate, and there is the mysterious 6, which is the setting when the loop exits, with some of these threads not having reached the println.
Hi was reading about that a string is thread safe because it is immutable.
For example i do:
String a = "test";
One thread uses this variable.
But another thread could still also use this variable and change it:
a = a + "something";
So it would change or not?
If it would be volatile, i would get it, that it can just be used by one thread at a time. But immutabilty doesnt guarantee me this!?
You're not changing the object pointed by a, but where a points to:
String a = "test";
here a points to a string "test"
a = a + "something";
here a new string is created as the result of the concatenation of "test" and "something", which "testsomething" where a points to. It's a different instance.
So there is no problem of thread safety, as both threads will have their own a referring to the same "test" string object, but once one of those thread will modify the string to be referring the "testsomething" object, the other Thread will still be referring the original "test" object.
The String itself isn't changing, the reference is. It sounds like you need the reference to be final. Immutability guarantees that the Object does not change, not that the reference cannot change. Just mark it like this:
final String a = "test";
You can make the code thread safe trivially by having each thread copy the reference a. In fact, that’s normally what happens anyway, since you usually pass the string to the thread via a parameter.
So both threads hold a reference to the original string, here "test". If thread 1 now modifies a it only modifies this reference. Thread 2 still retains an intact reference to "test" because the string itself (rather than the reference) is immutable.
Strings objects are thread-safe. If your String a is a local variable then this code is still thread-safe. If it is a field of your class than it is your responsibility to guarantee its thread-safety. Thread-safety of String won't magically make your own code thread-safe. You should take care about it.
You can make field volatile then you get visibility among threads. So any thread will see up-to-date value of your field. But you won't get atomicity in this way. Imagine the following. Let a = "test". Thread 1 updates a and thread 2 updates a. They both see current value which is "test". They read it, make new strings by concatenation and update value of a. And what will be that value? It is unknown. It can be "testsomethingsomething" if threads perform their operations strictly one after another. But it can be just "testsomething". For instance:
thread 1 read "test" from a
thread 2 read "test" from a
thread 2 updates a with "testsomething"
thread 1 updates a (remember, it read a as "test" before) with the same "testsomething"
Voila, you've lost an update to your field. To avoid this kind of problem, you should guard all accesses and modifications to your field with synchronization on single lock object.
A lot of confusion here...
What thread safety of some class means is that concurrent use of it's instance
will not destroy it's internal structure.
In our case it is just a warranty that we finally get a "testsomething", but not a mess like
"tsomethingest" or "tesomethingst" or "tseosmtething" or "somethingtest".
Here a "quick and dirty" illustration:
public class Test2 {
private volatile String tstStr = "";
Test2(){
}
void impl(int par){
Thread wrk = new Thread(new MyRun(par));
wrk.start();
}
static public void main(String[] args) throws Exception {
Test2 tst2 = new Test2();
long startTime = System.currentTimeMillis();
Thread wrk;
for (int i = 0; i < 9; i=i+1) {
tst2.impl(i);
}
long endTime = System.currentTimeMillis();
System.out.println("The process took " + (endTime - startTime) + " milliseconds");
}
class MyRun implements Runnable {
int no;
MyRun(int var){
no = var;
}
public void run(){
tstStr = tstStr + " " + no;
for (int i = 0; i < 3; i=i+1) {
System.out.println("Message from "+no+", tested string ="+tstStr);
}
}
}
}
The output:
Message from 1, tested string = 0
Message from 1, tested string = 0 2 3
Message from 1, tested string = 0 2 3
Message from 4, tested string = 0 2 3 4
Message from 4, tested string = 0 2 3 4
Message from 0, tested string = 0 2
Message from 8, tested string = 0 2 3 4 7 8
Message from 5, tested string = 0 2 3 4 7 8 5
Message from 0, tested string = 0 2 3 4 7 8 5
Message from 0, tested string = 0 2 3 4 7 8 5
The process took 0 milliseconds
Message from 7, tested string = 0 2 3 4 7
Message from 7, tested string = 0 2 3 4 7 8 5 6
Message from 4, tested string = 0 2 3 4
Message from 3, tested string = 0 2 3
Message from 2, tested string = 0 2
Message from 3, tested string = 0 2 3 4 7 8 5 6
Message from 7, tested string = 0 2 3 4 7 8 5 6
Message from 6, tested string = 0 2 3 4 7 8 5 6
Message from 5, tested string = 0 2 3 4 7 8 5
Message from 8, tested string = 0 2 3 4 7 8 5
Message from 5, tested string = 0 2 3 4 7 8 5 6
Message from 6, tested string = 0 2 3 4 7 8 5 6
Message from 3, tested string = 0 2 3 4 7 8 5 6
Message from 2, tested string = 0 2 3 4 7 8 5 6
Message from 6, tested string = 0 2 3 4 7 8 5 6
Message from 8, tested string = 0 2 3 4 7 8 5 6
Message from 2, tested string = 0 2 3 4 7 8 5 6