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
Related
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.
So I have a simple code that I want to print the value I 10 times with Thread1, after that 10 times of Thread2 and at the end, print the count ( it should be 20). I am using the ".join()" but the result is executing random times of Thread1 and Thread2 and then the Sum is correct. How can is it possible to print first all the Thread's1 loop and then the Tread's2 ??
class MyClass extends Thread {
public static synchronized void incount() {
SimpleThreads.count++;
}
public void run() {
for(int i=0; i<10; i++) {
incount();
System.out.println(Thread.currentThread().getId()+" value : " + i);
}
}
}
public class SimpleThreads {
static int count=0;
public static void main(String[] args) {
MyClass thread1 =new MyClass();
MyClass thread2 =new MyClass();
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" Sum : "+count);
}
}
The Result :
11 value : 0
10 value : 1
11 value : 1
10 value : 2
11 value : 2
10 value : 3
11 value : 3
11 value : 4
11 value : 5
11 value : 6
11 value : 7
11 value : 8
11 value : 9
10 value : 4
10 value : 5
10 value : 6
10 value : 7
10 value : 8
10 value : 9
Sum : 20
You are starting Thread2 before calling the join() on thread1.
That is why your both threads are basically running simultaneously and your join is not affecting the run() of any other the 2 threads.
Try to change your start and join calling code to something like this;
try{
thread1.start();
thread1.join();
thread2.start();
}
You shouldn't need to call join() on thread2 in this case.
If you want thread2 to start after thread1 terminates, then of-course you can simply wait for thread1 to terminate and then launch thread2. But then, what is the point of using threads?
If you want to launch thread1 and thread2 at the same time and still have thread2 wait until thread1 terminates, you can use one of Java's many concurrency utilities, such as Semaphore
The below code demonstrates the use of Semaphore. As you can see, just as in the code in your question, both threads - thread1 and thread2 - are launched at the same time. In the run() method of class MyClass, the code tries to acquire the semaphore. Method acquire() will block, i.e. it will not return, until it succeeds in acquiring the semaphore. Hence the first thread that manages to acquire the semaphore will run, while the other thread will wait until the first thread releases the semaphore. Note that I create the semaphore with only one permit which means that only one thread can acquire the semaphore at any one time. If you change the 1 to a 2 in the call to the Semaphore constructor, you will get exactly the same behavior as in your original code in your question, i.e. both threads will run simultaneously because both can immediately acquire the semaphore.
Note also that since I am using a semaphore, I don't need to call Thread.join() at all in order to have one thread wait until the other completes, but since you want to print the "sum" in the "main" thread, the "main" thread needs to wait, but it only needs to wait for the second thread to terminate.
Here is the code:
import java.util.concurrent.Semaphore;
class MyClass extends Thread {
private Semaphore semaphore;
public MyClass(Semaphore semaphore) {
this.semaphore = semaphore;
}
public static synchronized void incount() {
SimpleThreads.count++;
}
public void run() {
try {
semaphore.acquire();
for (int i = 0; i < 10; i++) {
incount();
System.out.println(Thread.currentThread().getId() + " value : " + i);
}
}
catch (InterruptedException xInterrupted) {
xInterrupted.printStackTrace();
}
finally {
semaphore.release();
}
}
}
public class SimpleThreads {
static int count = 0;
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(1);
MyClass thread1 = new MyClass(semaphore);
MyClass thread2 = new MyClass(semaphore);
thread1.start();
thread2.start();
try {
thread2.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" Sum : " + count);
}
}
And here is the output obtained when running the above code:
13 value : 0
13 value : 1
13 value : 2
13 value : 3
13 value : 4
13 value : 5
13 value : 6
13 value : 7
13 value : 8
13 value : 9
14 value : 0
14 value : 1
14 value : 2
14 value : 3
14 value : 4
14 value : 5
14 value : 6
14 value : 7
14 value : 8
14 value : 9
Sum : 20
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.
Consider the below code for Thread Synchronization Method and a Synchronization Block
public class ThreadSynchronizationPartI {
public static int myValue=1;
public static void main(String [] args)
{
Thread t=new Thread(()->
{
while(true)
{
updateBalance();
}
});
t.start();
t=new Thread(()->{
while(true)
{
monitorBalance();
}
});
t.start();
}
public static synchronized void updateBalance(){
System.out.println("start "+myValue);
myValue = myValue + 1;
// myValue = myValue - 1;
System.out.println("end "+myValue);
}
public static synchronized void monitorBalance(){
int b=myValue;
if(b>1)
{
System.out.println("B is greater than 1 by"+(b-1));
System.exit(1);
}
}
}
Why Does it give the following output:
start 1
end 2
start 2
end 3
start 3
end 4
start 4
end 5
start 5
end 6
start 6
end 7
start 7
end 8
B is greater than 1 by 7
Can anyone explain?
The execution of your program will start from main(). Initially the value of myValue is 1 and a new thread t will be created. Until the condition is true the while loop will be executed. When the control will reach updateBalance(), it will jump to that method and the println() will print the value of myValue which is 1. Hence the output will be : start 1 it will then increase the value of myValue to +1 and as a result the next println() would print the output as : end 2. When the condition for next thread will be true in while loop, the control will be transferred there. The monitorBalance() will be called and b is initialized the value of myValue. When the condition b>1 evaluates to true it will print : B is greater than 1 by (b-1).
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()