I'm taking Java lessons. We're now into threads. It is the first time I'm experiencing multithreading so please excuse me if the question is very dumb :)
I've the following program:
public class Foo extends Thread {
private int x = 2;
public static void main(String[]args) {
new Foo().fun();
}
Foo () {
x = 5;
start();
}
public void fun() {
x = x - 1;
System.out.println(x);
}
public void run() {
x = x * 2;
}
}
When I run the program I get 4 as output. Will the output of the above program always be 4?
It will NOT always be 4.
If the Foo run() method executes before the main thread runs fun(), it will be 9.
If the Foo run() method executes whilst main is running fun(), it will be 8.
If main() completes before Foo starts, it will be 4
No, not always. Because in ctor you calling start() method, there's race condition between call to fun from main thread and run which will change value of x from Thread.start.
But, actually, without presence of proper synchronization there no guarantees on what output will be, irrelevant to the order in which fun and run will be called. Because synchronization ensures visibility of changes to threads, output can be 4 even if run will finish before fun gets called.
As you said you are learning multi-threading, you must know that you can never predict the sequence of execution of different threads.
This is a very simple program where the main thread will almost always finish first - but important thing to remember is you can never be sure in complex multi-threaded scenarios. In fact, you chose mult-threaded approach mostly in scenarios when one thread isn't dependent on execution of another.
btw try changing constructor this way:
Foo () {
x = 5;
start();
Thread.sleep(2 * 1000);
}
you may get different result.
Simon's answer is correct with a caveat. Java has some caching of variable values. If a variable is not set as volatile or if you don't use an atomic value, you may get the cached value instead of the most recent value.
yes it will always be 4. i see no reason for it not to be 4
you only run fun() and never run()
read java Thread man
Related
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 5 years ago.
I have theoretical question about memory visibility. Here is sample code:
public class TwoThreadApp {
private static class A {
int x = 1;
}
public static void main(String[] arg) throws InterruptedException {
A a = new A();
Thread t2 = new Thread(() -> {
while (true) {
if (a.x == 2) {
System.out.println(a.x);
return;
}
// IO operation which makes a.x visible to thread "t2"
System.out.println("in loop");
}
});
t2.start();
Thread.sleep(100);
a.x = 2;
}
}
Without System.out.println("in loop") programs works indefinitely, which is expected behavior.
But with System.out.println("in loop") it is always completes, which is not expected, because a.x is not volatile and there is no synchronized blocks.
My env: ubuntu 16.04, openjdk 1.8.0_131
Why it behaves this way?
Without System.out.println("in loop") programs works indefinitely, which is expected behavior.
On the contrary, the program should quit. The program keeps going, that is side-effect of fact that x is cached (as non volatile). The caching is compiler's optimalization and you should not rely on it (depending on JVM settings).
But with System.out.println("in loop") it is always completes, which is not expected, because a.x is not volatile and there is no synchronized blocks.
This is IMHO expected behaviour. I cannot tell you why, I'd assume the IO operations are involved to clear the thread cache (please comment/correct if someone is having better insight).
Accessing variables without synchronization or locks or being volatile with multiple threads may be really unpredictable.
You can even disable many optimalizations with -Djava.compiler=NONE (then the program should always quit as expected)
IMHO this is something to do with Compiler optimization I think. In your first example compile can decide to move the If condition outside while loop like
if(a.x == 2) while(true) {...}
In 2nd case as you are using println which internally uses synchronized keyword compiler may not optimize the code as above.
This is what I think and I maybe wrong.
Edit: You can also refer here : Loop doesn't see changed value without a print statement
public class YieldDemo extends Thread{
public static void main(String[] args) {
YieldDemo y1 = new YieldDemo();
YieldDemo y2= new YieldDemo();
y1.start();
y2.start();
}
public void run() {
for(int i=0;i<=5;i++) {
if(i==3) {
Thread.yield();
} else
System.out.println(i+Thread.currentThread().toString());
}
}
}
As per the documentation of yield(), thread-1 should yield and allow thread-2 to process after 3rd loop. However, the output is not as expected. Same thread continues skipping 3rd iteration. After one thread completes the loop, other thread executes with same behaviour. Please explain.
Output:
0Thread[Thread-1,5,main]
1Thread[Thread-1,5,main]
2Thread[Thread-1,5,main]
4Thread[Thread-1,5,main]
5Thread[Thread-1,5,main]
0Thread[Thread-0,5,main]
1Thread[Thread-0,5,main]
2Thread[Thread-0,5,main]
4Thread[Thread-0,5,main]
5Thread[Thread-0,5,main]
The java.lang.Thread.yield() method causes the currently executing thread object to temporarily pause and allow other threads to execute.
NOTE : That other thread can be same thread again. There is no guarantee which thread be chosen by JVM.
As with almost all aspects of Multithreading, even your case isn't guaranteed to behave as expected. Thread.yield() is just like a suggestion to the OS telling - if it is possible, then please execute other threads before this one. Depending on the architecture of your system (number of cores, and other aspects like affinity etc etc) the OS might just ignore your request.
Also, after JDK6U23, the JVM might just change your code to :
public void run() {
for(int i=0;i<=5;i++) {
// 3 is too darn small. and yield() is not necessary
// so let me just iterate 6 times now to improve performance.
System.out.println(i+Thread.currentThread().toString());
}
yield() can totally be ignored (which might be happening in your case. If you are getting the same result over and over again)
Read This article. yield method is to request for a thread to sleep. it may be happen or not.
I have a class with a getter getInt() and a setter setInt() on a certain field, say field
Integer Int;
of an object of a class, say SomeClass.
The setInt() here is synchronized-- getInt() isn't.
I am updating the value of Int from within multiple threads.
Each thread is getting the value Int, and setting it appropriately.
The threads aren't sharing any other resources in any way.
The code executed in each thread is as follows.
public void update(SomeClass c) {
while (<condition-1>) // the conditions here and the calculation of
// k below dont have anything to do
// with the members of c
if (<condition-2>) {
// calculate k here
synchronized (c) {
c.setInt(c.getInt()+k);
// System.out.println("in "+this.toString());
}
}
}
The run() method is just invoking the above method on the members updated from within the constructor by the params passed to it:
public void run() { update(c); }
When I run this on large sequences, the threads aren't interleaving much-- i see one thread executing for long without any other thread running in between.
There must be a better way of doing this.
I can't change the internals of SomeClass, or of the class invoking the threads.
How can this be done better?
TIA.
//=====================================
EDIT:
I'm not after manipulating the execution sequence of the threads. They all have the same priority. It`s just that what i see in the outcome is suggesting that the threads aren't sharing the execution time evenly-- one of them, once takes over, executing on. However, I can't see why this code should be doing this.
It`s just that what i see in the outcome is suggesting that the threads aren't sharing the execution time evenly
Well, this is exactly what you don't want if you are after efficiency. Yanking a thread from being executed and scheduling another thread is generally very costly. Therefore it's actually advantageous to do one of them, once takes over, executing on. Of course, when this is overdone you could see higher throughput but longer response time. In theory. In practice, JVMs thread scheduling is well tuned for almost all purposes, and you don't want to try changing it in almost all situations. As a rule of thumb, if you are interested in response times in millisecond order, you probably want to stay away messing with it.
tl;dr: It's not being inefficient, you probably want to leave it as it is.
EDIT:
Having said that, using an AtomicInteger may help in performance, and is in my opinion less error prone than using a lock (synchronized keyword). You need to be hitting that variable really very hard in order to get a measurable benefit though.
The JDK provides a nice solution for multi threaded int access, AtomicInteger:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html
As Enno Shioji has pointed out, letting one thread proceed might be the most efficient way to execute your code in some scenarios.
It depends on how much cost the thread synchronization imposes in relation to the other work of your code (which we don’t know). If you have a loop like:
while (<condition-1>)
if (<condition-2>) {
// calculate k here
synchronized (c) {
c.setInt(c.getInt()+k);
}
}
and the test for condition-1 and condition-2 and the calculation of k is rather cheap compared to the synchronization cost, the Hotspot optimizer might decide to reduce the overhead by transforming the code to something like this:
synchronized (c) {
while (<condition-1>)
if (<condition-2>) {
// calculate k here
c.setInt(c.getInt()+k);
}
}
(or a rather more complicated structure by performing loop unrolling and span the synchronized block over multiple iterations). The bottom line is that the optimized code might block other threads longer but let the one owning the lock finish faster resulting in an overall faster execution.
This does not mean that a single-threaded execution was the fastest way to handle your problem. It also doesn’t mean that using an AtomicInteger here would be the best option to solve the problem. It would create a higher CPU load and possibly a small acceleration but it doesn’t solve your real mistake:
It is completely unnecessary to update c within the loop at a high frequency. After all, your threads do not depend on seeing updates to c timely. It even looks like they are not using it at all. So the correct fix would be to move the update out of the loop:
int kTotal=0;
while (<condition-1>)
if (<condition-2>) {
// calculate k here
kTotal += k;
}
synchronized (c) {
c.setInt(c.getInt()+kTotal);
}
Now, all threads can run in parallel (assuming the code you haven’t posted here doesn’t contain inter-thread dependencies) and the synchronization cost is reduced to a minimum. You could still change it to an AtomicInteger as well but that’s not that important anymore.
Answering to this
i see one thread executing for long without any other thread running in between.
There must be a better way of doing this.
You can not control how threads will be executed. JVM does this for you, and does not like you to interfere in its work.
Still you can look at yield as your option, but that also does not ensure same thread will not be picked again.
The java.lang.Thread.yield() method causes the currently executing thread object to temporarily pause and allow other threads to execute.
I've found it better to use wait() and notify() than yield. Check out this example (seen from a book)-
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
if(!valueSet)
wait(); //handle InterruptedException
//
valueSet = false;
notify();//if thread waiting in put, now notified
}
synchronized void put(int n) {
if(valueSet)
wait(); //handle InterruptedException
//
valueSet = true;
//if thread in get waiting then that is resumed now
notify();
}
}
or you could try using sleep() and join the threads in the end in main() but that isn't a foolproof way
You are having public void update(SomeClass c) method in your code and this method is an instance method in which you are passing the object as parameter.
synchronized(c) in your code is doing nothing. Let me show you with some example,
So if you will make different objects of this class and then try to make them different threads like,
class A extends Thread{
public void update(SomeClass c){}
public void run(){
update(c)
}
public static void main(String args[]){
A t1 = new A();
A t2 = new A();
t1.start();
t2.start();
}
}
Then both of these t1 & t2 will have their own copies of update method and the reference variable c which you are making synchronized will also be different for both the threads. t1 calls its own update() method and t2 calls its own update() method. So synchronization won't work.
Synchronization will work when you have something common for both the threads.
Something like,
class A extends Thread{
static SomeClass c;
public void update(){
synchronized(c){
}
}
public void run(){
update(c)
}
public static void main(String args[]){
A t1 = new A();
A t2 = new A();
t1.start();
t2.start();
}
}
This way the actual concept of synchronization will be applied.
Why does the below program output 11 and not 12?.
Does not the thread use the same instance variables? Please explain?
public class Tester extends Thread {
private int i;
public static void main(String[] args){
Tester t = new Tester();
t.run();
System.out.print(t.i);
t.start();
System.out.print(t.i);
}
public void run(){ i++;}
}
The above code compiles fine. i is defaulted to 0 value on construction of object.
In happens before relation concept all code executed prior to start of thread is completed.
The concept is - instance variables are shared across multiple threads - here there are two threads running - the main thread and the Tester thread. So i should shared with both threads? - if i is shared and if happens-before relation is maintained before starting Tester thread then the value of incremented i should be visible to the Tester thread?
Give to your new thread the time to increase the variable, try with
public static void main(String[] args){
Tester t = new Tester();
t.run();
System.out.println(t.i);
t.start();
try {
Thread.sleep(1000); // 1 sec
} catch (Exception ex) {}
System.out.println(t.i);
}
The only problem in your code is that you print the t.i value and do not wait after t.start(), you print the value before the thread increases it.
The instance variable can be accessed by multiple threads if you let them, for example making it public, or by any other means.
In your code this is what happens: The Tester thread t will access it's own variable, and you will access also that same variable from the main thread. For the moment when you ask it to print the value, it may print any value by which the Testet thread t is at the moment.
When the main thread calls the run method it will execute in the main thread, effectively increasing the value of the field to 1 (as 0 is the default). Afterwards when you call the method start it will start the separate thread and the Java VM will call the method run, then again the field gets incremented, this time from 1 to 2.
So, I would expect that the output is 1 and then, possible 1 or possibly 2 depending on whatever there was time for the thread to execute before you asked to print the value from the main thread.... the exact result you get depends on your machine, in another computer it can be another tale. This depends on the CPU, the operating system, the available memory and other things.
As dash1e suggested in his answer, you can use Thread.sleep(1000); to make the main thread wait while the Tester thread t executes on background. This greatly increases the likelihood that the Tester thread t will have updated the value of the field before the main thread asks for it to print it. That said, I want to left clear that using Thread.sleep(1000); to wait for a task to complete is not good enough by itself... if you want to, you can put a call to Thread.sleep inside a while where you verify if a certain criteria has been met, that's known as an spinning.
The fact that you can print the value of the field form the main thread demostrates that you can access it from another thread. And that is a good thing, because you want your thread to communicate... somehow.
It is ok to access it because it is only an int, and an int cannot be in an invalid state, so there is no need sync the access. Although you may get an not up-to-date value, and it will change on background, so it isn't very reliable.
If you want a value that can only be acceded by a single thread, and that exists idependly for each thread, then take a look to ThreadLocal.
The main answer that I was looking for was in terms of happens-before: Concept detailed below:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility
So it says in the docs -
a) that before a thread starts - all statements prior to it are completed
b) all statements in the thread execution are completed at the termination of the new thread.
Going with the above understanding - i should be all the time visible to the new thread started. And this it should be - at all times, on all systems - so when start is called and a new thread is launched then it should always see i as 1.
But, the time we are printing the i value is getting executed by the main thread - not by the Tester thread. So even though the new Tester thread may see the value as 1 and increment it as 2 - the execution in main does not reflect it because i++ is not an atomic operation.
Now suppose we try and make the int as :
private volatile int i;
volatile guarantees happens-before relationship for not only the specific variable but also statement until it.
The println of main thread that gets executed may get executed before the increment even began. So we may see 11 getting printed, even after making the variable volatile. Similar case exists for making the variable an AtomicInteger.
The run method when invoked will see the incremented value:
System.out.println("i "+ i.incrementAndGet());
But not the main thread. Visibility of data in the run method / main method differs.
Instance variable used is same for both threads executing.
You have started the thread, but have not wait for it to stop. Use t.join() to wait for finish. And, yes, you have thread synchronization issue, but that's another issue.
public class Tester extends Thread {
private int i;
public static void main(String[] args) throws InterruptedException {
Tester t = new Tester();
t.run();
System.out.println(t.i);
t.start();
t.join();
System.out.println(t.i);
}
public void run() {
i++;
}
}
I your code:
public class Tester extends Thread {
private int i;
public static void main(String[] args){
Tester t = new Tester();
t.run();
System.out.print(t.i);
t.start();
System.out.print(t.i);
}
public void run(){ i++;}
}
You call t.run() and t.start(). There are 2 thread are running t.run() thread and t.start() thread.
In that i variable you share between 2 thread that is not synchronous.
Therefore sometime value of i variable is not update between threads.
You can synchronous by using volatile keyword
private volatile int i;
Or synchronise code segment increases value of i
public void run(){
synchronized(this){
i++;
}
}
Why would the compiler print 2 a and then 2 b or vice versa when giving the priority to Thread a to start? Shouldn't thread b wait for thread a to finish in order to start? Can someone please explain how does it work?
public class Test1 extends Thread{
static int x = 0;
String name;
Test1(String n) {
name = n;
}
public void increment() {
x = x+1;
System.out.println(x + " " + name);
}
public void run() {
this.increment();
}
}
public class Main {
public static void main(String args[]) {
Test1 a = new Test1("a");
Test1 b = new Test1("b");
a.setPriority(3);
b.setPriority(2);
a.start();
b.start();
}
}
Giving priorities is not a job for the compiler. It is the OS scheduler to schedule and give CPU time (called quantum) to threads.
The scheduler further tries to run as much threads at once as possible, based on the available number of CPUs. In today's multicore systems, more often than not more than one core are available.
If you want for a thread to wait for another one, use some synchronizing mechanism.
Shouldn't thread b wait for thread a to finish in order to start?
No. The priority does not block the thread execution. It only tells the JVM to execute the thread "in preference to threads with lower priority". This does imply a wait.
Since your code is so trivial, there is nothing to wait for. Any of the two threads is run.
Why would the compiler print 2 a and then 2 b?
Luck of the draw. "Priority" means different things on different operating systems, but in general, it's always part of how the OS decides which thread gets to run and which one must wait when there's not enough CPUs available to run them both at the same time. If you computer has two or more idle CPUs when you start that program, then everybody gets to run. Priority doesn't matter in that case, and its just a race to see which one gets to the println(...) call first.
The a thread in your example has an advantage because the program doesn't call b.start() until after the a.start() method returns, but how big that advantage actually is depends on the details of the OS thread scheduling algorithm. The a thread could get a huge head start (like, it actually finishes before b even starts), or it could be a near-trivial head start.