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.
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
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
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()
I am trying to make a program that runs several parallel readers and writers. I start some threads in a loop using ExecutorService class, the run() method of the Writer class just call two methods StartWrite()and EndWrite() and for the Reader class, StartRead() and EndRead(). These methods are wrapped in a monitor.
Here's the monitor:
public class RWMonitorAN {
static int readers = 0;
static boolean writing = false;
public static RandomAccessFile f;
public static int n = 0;
private final ReentrantLock mylock = new ReentrantLock();
private final Condition toWrite = mylock.newCondition();
private final Condition toRead = mylock.newCondition();
public RWMonitorAN()
{
try { f = new RandomAccessFile("datos.dat", "rw"); } catch (IOException e) {}
}
void StartRead() {
mylock.lock();
try
{
if (writing)
try {
toRead.wait();
toWrite.wait();
} catch (InterruptedException e) {}
readers++;
try
{
f.seek(0);
while (f.getFilePointer()<f.length())
System.out.print(f.readInt()+" ");
System.out.println();
} catch (IOException e) { e.printStackTrace(); }
}
finally { mylock.unlock(); }
}
void EndRead() {
mylock.lock();
try
{
readers--;
if (readers == 0)
toWrite.signal();
}
finally { mylock.unlock(); }
}
void StartWrite() {
mylock.lock();
try
{
if (writing || readers != 0)
try {
toWrite.wait();
} catch (InterruptedException e) {}
writing = true;
try
{
f.writeInt(n);
} catch(IOException e) {}
n++;
}
finally { mylock.unlock(); }
}
void EndWrite() {
mylock.lock();
try
{
writing = false;
toWrite.signal();
toRead.signal();
}
finally { mylock.unlock(); }
}
But there's a problem: the program ends before the expected number of data is written and read. For example, if I start 20 writer and 20 reader threads, I expect 20 numbers to be written and read, but only 10~ are. If I run the program again (datos.dat would be already created) it keeps writing and reading and then 20 numbers are written.
Test:
1st run
Written in the last executed thread: 0 1 2 3 4
Read in the last executed thread: 0 1 2 3 4
2nd run
Written in the last executed thread: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Read in the last executed thread: 0 1 2 3 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
What's wrong? How can I make it work properly?
EDIT: I tried printing the number of readers every time a reader finishes reading and the same number of readers is being printed several times. Shouldn't this not be happening? readers-- is executed in a lock protected section of the code.
You are catching your exceptions everywhere and not reporting them anywhere nor do anything else to serve them. The first thing to "make it work properly" would probably be to check if there are exceptions called. For example, if you use more than one iterators on one data structure in Java it will probably throw concurrentModificationException at the start, to prevent unexpected behaviour in the future.
What is the point of using multiple readers from a file if, as it appears, you set every new one to the very beginning of a file with seek(0)? And your reader appears to try to read the whole file
while (f.getFilePointer()<f.length())
System.out.print(f.readInt()+" ");
and your writer tries to read a single int in
f.writeInt(n);
so if you started n threads I would not expect n numbers to be read.
Finally, have you considered what happens when you start another writer/reader after startRead unlocked mylock but before EndRead locked it again? Why not to put the logic from EndRead just at the end of startRead method then?
so i was testing with synchronized keyword. Here is an example that I tried:
public class MyTest {
static int i = 0;
public static void main(String[] args) {
new Thread(t1).start();
new Thread(t2).start();
}
private static void countMe(String name){
i++;
System.out.println("Current Counter is: " + i + ", updated by: " + name);
}
private static Runnable t1 = new Runnable() {
public void run() {
try{
for(int i=0; i<5; i++){
countMe("t1");
}
} catch (Exception e){}
}
};
private static Runnable t2 = new Runnable() {
public void run() {
try{
for(int i=0; i<5; i++){
countMe("t2");
}
} catch (Exception e){}
}
};
}
When I run it, the output of calling countMe() method from two threads generates this output:
Current Counter is: 1
Current Counter is: 2
Current Counter is: 4
Current Counter is: 5
Current Counter is: 6
Current Counter is: 7
Current Counter is: 3
Current Counter is: 8
Current Counter is: 9
Current Counter is: 10
And when I change the method countMe() to:
private synchronized static void countMe(){
i++;
System.out.println("Current Counter is: " + i);
}
I get this output:
Current Counter is: 1
Current Counter is: 2
Current Counter is: 3
Current Counter is: 4
Current Counter is: 5
Current Counter is: 6
Current Counter is: 7
Current Counter is: 8
Current Counter is: 9
Current Counter is: 10
Although this gives me clear understanding the purpose of synchronized, I want to know is there any other reason as well, that we can use synchronized. Or what I have done here, is the only eason why we need the use of this synchronized keyword?
Thanks.
EDIT: Another thing that I am confused with is that in first output why the counter went to 3 after 7. It seems a bit impossible to me, but similar results do happen every time I try, is this normal?
Two things:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods. (An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed).
source: http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Vulkanino gave a good answer to your main question, so I'll only address your question about 3 printing after 7.
The 3 can print after the 7 because there is actually a lot more byte code in your statements than Java code.
I'll expand on that.
You call
System.out.println("Current Counter is: " + i);
and it occurs in one line of Java code, but really what happens is a string is created and then that string is passed to println. The println method itself has to do a bit of processing before it actually writes the line to the console.
Conceptually, something like the following is happening.
String printlnString = "Current Counter is: 3"
--> maybe the other thread executes here
System.out.println(printlnString);
--> or maybe the other thread executes here
i is now equal to 7 and the console has "Current Counter is: 7"
println writes "Current Counter is: 3" to console