I'm doing a college class on Java concurrency and was recently given a simple task to create 5 threads numbered from 1 to 5, then get each thread to write its thread number to a static variable in the class using a synchronized static method.
The solution I was given by the lecturer is below:
public class thread1 extends Thread {
private int threadNumber;
private static int threadCount = 0;
private static int value;
public thread1(){
threadNumber = ++threadCount;
System.out.println("Thread " + threadNumber + " is created" );
}
public synchronized static void setValue(int v){
value = v;
try{
Thread.currentThread().sleep(100);
}
catch(InterruptedException e ){}
System.out.println("the current value of the variable is " + value);
}
public void run() {
setValue(threadNumber);
return;
}
public static void main(String[] args) {
for(int i = 0; i < 5; i++){
thread1 thr = new thread1();
thr.start();
}
}
}
The output is supposed to be as follows:
Thread 1 is created Thread 2 is created Thread 3 is
created Thread 4 is created Thread 5 is created the
current value of the variable is 1 the current value of the
variable is 2 the current value of the variable is 3 the
current value of the variable is 4 the current value of the
variable is 5
But the output I am getting is below:
Thread 1 is created Thread
2 is created Thread 3 is created Thread 4 is created
Thread 5 is created the current value of the variable is 1
the current value of the variable is 5 the current value of the
variable is 4 the current value of the variable is 3 the
current value of the variable is 2
The order of current value is obviously different each time.
Is the solution I've been given incorrect? It's obviously not working in fulfilling its intended purpose which is to print out each of the thread's value variables in order.
Could anyone shed some light on how I'd get it to print the thread numbers in order from 1 to 5 each time reliably? I thought the use of the synchronized setValue method would do the trick, but obviously not.
The Solution provided by your lecturer is absolutely correct.
You are not getting the intended order because 5 different Threads are created and each of them have to access the same method which is Synchronized.
When a method is Synchronized only One Object at a time can access it
In your case Only One Thread can access the setValue method,
when one Thread enters the method it acquires the lock and
the other threads wait for the lock ,when this Thread releases the lock ,
any waiting Thread can acquire it and execute the setValue method.
You can never guarantee in which order Threads will execute the method,
so you will get some different order of Threads on running this program eachtime
There is no guarantee that threads will execute in the order you call start method on them.
A synchronized block only means that two threads cannot access it simultaneously. The order of the thread to run is determined by scheduler.
The order in which the thread enters the monitor is not defined. Once a thread finishes execution inside the monitor any other thread waiting on that monitor can gain control of the critical section.
Related
I am wondering what happens in the following scenario:
Two threads are created:
Thread t1 = new Thread();
Thread t2 = new Thread();
Assume these just print out a string, the threads then call the .start() method:
t1.start();
t2.start():
My question is why do these threads print in a seemingly random order each time? I know threads execute concurrently but would t1 not always finish before t2 due to the sequential execution of the main process?
Calling start() on a Thread doesn't necessarily result in the thread running immediately after. It is possible for other things to happen in between your calling start() and the first line of your thread's run() method actually being run. And even once your run() is actually running, it's also possible that other things happen before, during, or after your run() method finishes.
In your question, you said: "assume these just print out a string" – here's an implementation of run() which does that:
public void run() {
System.out.println("my name is: " + getName());
}
So it's possible that t1 starts to run first, but before it actually calls System.out.println, t2 is allowed to execute and runs to completion, then t1 is resumed.
If this kind of behavior won't work for your use case, you'll need to add some kind of concurrency protection to coordinate how and when your threads run.
UPDATE:
To illustrate the unpredictable sequence of thread execution, run this code a few times and observe the output:
public class Example {
public static void main(String[] args) {
for (int k = 0; k < 10; k++) {
new TestThread(k).start();
}
}
}
class TestThread extends Thread {
private final int k;
TestThread(int k) {
this.k = k;
}
#Override
public void run() {
System.out.print(k + " ");
}
}
Here is the output from one of my local runs:
7 0 1 5 4 6 3 2 8 9
Thread.start() doesn't guarantee execution. It will just make the Thread state runnable and hand over to the Thread Scheduler. It is the Thread Scheduler which decides which thread to run when.
If you need code to execute in a defined order on multiple threads, you need to add synchronization code between those threads.
Otherwise, the system is free to schedule execution in any order it sees fit.
Consider the following simple example:
public class Example extends Thread {
private int internalNum;
public void getNum() {
if (internalNum > 1)
System.out.println(internalNum);
else
System.out.println(1000);
}
public synchronized modifyNum() {
internalNum += 1;
}
public void run() {
// Some code
}
}
Let's say code execution is split in two threads. Hypothetically, following sequence of events occurs:
First thread accesses the getNum method and caches the internalNum which is 0 at the moment.
At the very same time second thread accesses modifyNum method acquiring the lock, changes the internalNum to 1 and exits releasing the lock.
Now, first thread continues it execution and prints the internalNum.
The question is what will get printed on the console?
My guess is that this hypothetical example will result in 1000 being printed on the console because read and write flushes are only forced on a particular thread when entering or leaving the synchronized block. Therefore, first thread will happily use it's cached value, not knowing it was changed.
I am aware that making internalNum volatile would solve the possible issue, however I am only wondering weather it is really necessary.
Let's say code execution is split in two threads.
It doesn't exit. However a ressource (method, fields) may be accessed in concurrent way by two threads.
I think you mix things. Your class extends Thread but your question is about accessing to a resource of a same instance by concurrent threads.
Here is the code adapted to your question.
A shared resource between threads :
public class SharedResource{
private int internalNum;
public void getNum() {
if (internalNum > 1)
System.out.println(internalNum);
else
System.out.println(1000);
}
public synchronized modifyNum() {
internalNum += 1;
}
public void run() {
// Some code
}
}
Threads and running code :
public class ThreadForExample extends Thread {
private SharedResource resource;
public ThreadForExample(SharedResource resource){
this.resource=resource;
}
public static void main(String[] args){
SharedResource resource = new SharedResource();
ThreadForExample t1 = new ThreadForExample(resource);
ThreadForExample t2 = new ThreadForExample(resource);
t1.start();
t2.start();
}
}
Your question :
Hypothetically, following sequence of events occurs:
First thread accesses the getNum method and caches the internalNum
which is 0 at the moment. At the very same time second thread accesses
modifyNum method acquiring the lock, changes the internalNum to 1 and
exits releasing the lock. Now, first thread continues it execution and
prints the internalNum
In your scenario you give the impression that the modifyNum() method execution blocks the other threads to access to non synchronized methods but it is not the case.
getNum() is not synchronized. So, threads don't need to acquire the lock on the object to execute it. In this case, the output depends simply of which one thread has executed the instruction the first :
internalNum += 1;
or
System.out.println(internalNum);
public class MyStack2 {
private int[] values = new int[10];
private int index = 0;
public synchronized void push(int x) {
if (index <= 9) {
values[index] = x;
Thread.yield();
index++;
}
}
public synchronized int pop() {
if (index > 0) {
index--;
return values[index];
} else {
return -1;
}
}
public synchronized String toString() {
String reply = "";
for (int i = 0; i < values.length; i++) {
reply += values[i] + " ";
}
return reply;
}
}
public class Pusher extends Thread {
private MyStack2 stack;
public Pusher(MyStack2 stack) {
this.stack = stack;
}
public void run() {
for (int i = 1; i <= 5; i++) {
stack.push(i);
}
}
}
public class Test {
public static void main(String args[]) {
MyStack2 stack = new MyStack2();
Pusher one = new Pusher(stack);
Pusher two = new Pusher(stack);
one.start();
two.start();
try {
one.join();
two.join();
} catch (InterruptedException e) {
}
System.out.println(stack.toString());
}
}
Since the methods of MyStack2 class are synchronised, I was expecting the output as
1 2 3 4 5 1 2 3 4 5. But the output is indeterminate. Often it gives : 1 1 2 2 3 3 4 4 5 5
As per my understanding, when thread one is started it acquires a lock on the push method. Inside push() thread one yields for sometime. But does it release the lock when yield() is called? Now when thread two is started, would thread two acquire a lock before thread one completes execution? Can someone explain when does thread one release the lock on stack object?
A synchronized method will only stop other threads from executing it while it is being executed. As soon as it returns other threads can (and often will immediately) get access.
The scenario to get your 1 1 2 2 ... could be:
Thread 1 calls push(1) and is allowed in.
Thread 2 calls push(1) and is blocked while Thread 1 is using it.
Thread 1 exits push(1).
Thread 2 gains access to push and pushes 1 but at the same time Thread 1 calls push(2).
Result 1 1 2 - you can clearly see how it continues.
When you say:
As per my understanding, when thread one is started it acquires a lock on the push method.
that is not quite right, in that the lock isn't just on the push method. The lock that the push method uses is on the instance of MyStack2 that push is called on. The methods pop and toString use the same lock as push. When a thread calls any of these methods on an object, it has to wait until it can acquire the lock. A thread in the middle of calling push will block another thread from calling pop. The threads are calling different methods to access the same data structure, using the same lock for all the methods that access the structure prevents the threads from accessing the data structure concurrently.
Once a thread gives up the lock on exiting a synchronized method the scheduler decides which thread gets the lock next. Your threads are acquiring locks and letting them go multiple times, every time a lock is released there is a decision for the scheduler to make. You can't make any assumptions about which will get picked, it can be any of them. Output from multiple threads is typically jumbled up.
It seems like you may have some confusion on exactly what the synchronized and yield keywords mean.
Synchronized means that only one thread can enter that code block at a time. Imagine it as a gate and you need a key to get through. Each thread as it enters takes the only key, and returns it when they are done. This allows the next thread to get the key and execute the code inside. It doesn't matter how long they are in the synchronized method, only one thread can enter at a time.
Yield suggests (and yes its only a suggestion) to the compiler that the current thread can give up its allotted time and another thread can begin execution. It doesn't always happen that way, however.
In your code, even though the current thread suggest to the compiler that it can give up its execution time, it still holds the key to the synchronized methods, and therefore the new thread cannot enter.
The unpredictable behavior comes from the yield not giving up the execution time as you predicted.
Hope that helped!
I have written a program on synchronized block by locking on .class, and my program is executing thread by thread. But when i write the same code using synchronized method, the output is entirely different.
Synchronized block program given below:
public class SyncBlock {
public static void main(String[] args) {
final Thread t1 = new SimpleThread("First Thread");
final Thread t2 = new SimpleThread("Second Thread");
t1.start();
t2.start();
}
}
class SimpleThread extends Thread {
public SimpleThread(String str) {
super(str);
}
public void run() {
synchronized (SyncBlock.class) {
for (int i = 0; i < 5; i++) {
System.out.println(getName() + " says " + i);
try {
sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
}
}
System.out.println(getName() + " is done.");
}
}
}
The out put is:
First Thread says 0
First Thread says 1
First Thread says 2
First Thread says 3
First Thread says 4
First Thread is done.
Second Thread says 0
Second Thread says 1
Second Thread says 2
Second Thread says 3
Second Thread says 4
Second Thread is done.
Now i am using the same program using synchronized method. But it is behaving differently. Could you please explain whether both will behave differently or is there any solution to get same output using both synchronized block and method.
Using synchronized method:
now synchronize the run method and replace this code:
public synchronized void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName() + " says " + i);
try {
sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
}
}
System.out.println(getName() + " is done.");
}
Here the output is different:
First Thread says 0
Second Thread says 0
Second Thread says 1
First Thread says 1
First Thread says 2
Second Thread says 2
First Thread says 3
Second Thread says 3
First Thread says 4
First Thread is done.
Second Thread says 4
Second Thread is done.
In your synchronized block you are locking class object which will lock execution of run method on other objects when one object has invoked it. But when you synchronized run method, you will lock object not class, so it will not block another thread to execute same method on another object. Hence both thread executes in parallel. If you want to achieve same execution as with synchronized block you can have a synchronized static method which executes steps that are in run and call it from run method
When you use : synchronized (SyncBlock.class), your code works fine because you are locking on the SyncBlock class, so other thread cannot get access to the class Object of SyncBlock until the first one releases it.
In the second case, you are locking on the current instance of SimpleThread(this), the lock will be different for both threads (you are locking on the SimpleThread instances themselves). So, the lock itself is in-effective and the JVM might as well remove the synchronization code (from jdk6 U23 - escape analysis was introduced to optimize such things)
In case of synchronized block say First thread enters first
synchronized (SyncBlock.class) {--> // here First thread takes the lock now no other thread can enter
Now when First thread reaches here
System.out.println(getName() + " is done.");
} ---> here First thread releases the lock . So this gives chance to other thread which are waiting for this lock . so in ur case Second thread takes it and then executes it and when it reaches here it will release and then again other thread can take over. Note : This behavior is not definite
Threads can execute in any manner Depends upon CPU scheduling policy
And what happens in synchronized method is as soon as one thread enters this method it will complete its task and then release the lock .After this other thread gets the chance to execute .
Also note that sleep doesnt release the LOCK . at that stage thread is in wait state
None of the other answers here is wrong, but none of them really speaks to the heart of the matter.
When you write synchronized, your code synchronizes on an Object, and the JVM guarantees that no two threads can be synchronized on the same object at the same time.
In your first example, the SimpleThread.run() method synchronizes on the unique SyncBlock class object. That prevents both threads from entering run() at the same time because they both are trying to synchronize on the same object: there is only one SyncBlock class object.
In your second example, the SimpleThread.run() method synchronizes on this. That does not prevent the two threads from entering run() at the same time because the two threads are synchronizing on two different objects: You create two instances of SimpleThread.
I've read that "volatile" in Java allows different threads to have access to the same field and see changes the other threads has made to that field. If that's the case, I'd predict that when the first and second thread have completely run, the value of "d" will be incremented to 4. But instead, each thread increments "d" to a value of 2.
public class VolatileExample extends Thread {
private int countDown = 2;
private volatile int d = 0;
public VolatileExample(String name) {
super(name);
start();
}
public String toString() {
return super.getName() + ": countDown " + countDown;
}
public void run() {
while(true) {
d = d + 1;
System.out.println(this + ". Value of d is " + d);
if(--countDown == 0) return;
}
}
public static void main(String[] args) {
new VolatileExample("first thread");
new VolatileExample("second thread");
}
}
The results from running this program are:
first thread: countDown 2. Value of d is 1
second thread: countDown 2. Value of d is 1
first thread: countDown 1. Value of d is 2
second thread: countDown 1. Value of d is 2
I understand that if I add keyword "static" the program,
(that is, "private static volatile int d = 0;"), "d" would be incremented to 4.
And I know that's because d will become a variable that the whole class shares rather than each instance getting a copy.
The results look like:
first thread: countDown 2. Value of d is 1
first thread: countDown 1. Value of d is 3
second thread: countDown 2. Value of d is 2
second thread: countDown 1. Value of d is 4
My question is, why doesn't "private volatile int d = 0; " yield similar results if volatile is supposed to allow the sharing of "d" between the two threads? That is, if the first thread updates the value of d to 1, then why doesn't the second thread grab the value of d as 1 rather than as zero?
volatile doesn't "allow the sharing" of anything. It just prevents the variable from being cached thread local, so that changes to the variables value occur immediately. Your d variable is an instance variable and is thus owned by the instance that holds it. You'll want to re-read the threading tutorials to re-align your assumptions.
One decent reference is here
There are a couple of misunderstandings here. You seem not to properly understand what a thread is, what an instance field is and what a static field is.
An instance field is a memory location that gets allocated once you instantiate a class (ie, a memory location gets allocated for a field d when you VolatileExample v = new VolatileExample()). To reference that memory location from within the class, you do this.d (then you can write to and read from that memory location). To reference that memory location from outside the class, it must be acessible (ie, not private), and then you'd do v.d. As you can see, each instance of a class gets its own memory location for its own field d. So, if you have 2 different instances of VolatileExample, each will have its own, independent, field d.
A static field is a memory location that gets allocated once a class is initialized (which, forgetting about the possibility of using multiple ClassLoaders, happens exactly once). So, you can think that a static field is some kind of global variable. To reference that memory location, you'd use VolatileExample.d (accessibility also applies (ie, if it is private, it can only be done from within the class)).
Finally, a thread of execution is a sequence of steps that will be executed by the JVM. You must not think of a thread as a class, or an instance of the class Thread, it will only get you confused. It is as simple as that: a sequence of steps.
The main sequence of steps is what is defined in the main(...) method. It is that sequence of steps that the JVM will start executing when you launch your program.
If you want to start a new thread of execution to run simultaneously (ie, you want a separate sequence of steps to be run concurrently), in Java you do so by creating an instance of the class Thread and calling its start() method.
Let's modify your code a little bit so that it is easier to understand what is happening:
public class VolatileExample extends Thread {
private int countDown = 2;
private volatile int d = 0;
public VolatileExample(String name) {
super(name);
}
public String toString() {
return super.getName() + ": countDown " + countDown;
}
public void run() {
while(true) {
d = d + 1;
System.out.println(this + ". Value of d is " + d);
if(--countDown == 0) return;
}
}
public static void main(String[] args) {
VolatileExample ve1 = new VolatileExample("first thread");
ve1.start();
VolatileExample ve2 = new VolatileExample("second thread");
ve2.start();
}
}
The line VolatileExample ve1 = new VolatileExample("first thread"); creates an instance of VolatileExample. This will allocate some memory locations: 4 bytes for countdown and 4 bytes for d. Then you start a new thread of execution: ve1.start();. This thread of execution will access (read from and write to) the memory locations described before in this paragraph.
The next line, VolatileExample ve2 = new VolatileExample("second thread"); creates another instance of VolatileExample, which will allocate 2 new memory locations: 4 bytes for ve2's countdown and 4 bytes for ve2's d. Then, you start a thread of execution, which will access THESE NEW memory locations, and not those described in the paragraph before this one.
Now, with or without volatile, you see that you have two different fields d : each thread operates on a different field. Therefore, it is unreasonable for you to expect that d would get incremented to 4, since there's no single d.
If you make d a static field, only then both threads would (supposedly) be operating on the same memory location. Only then volatile would come into play, since only then you'd be sharing a memory location between different threads.
If you make a field volatile, you are guaranteed that writes go straight to the main memory and reads come straight from the main memory (ie, they won't get cached on some -- extremely fast -- processor-local cache, the operations would take longer but would be guaranteed to be visible to other threads).
It wouldn't, however, guarantee that you'd see the value 4 stored on d. That's because volatile solves visibility problem, but not atomicity problems: increment = read from main memory + operation on the value + write to main memory. As you can see, 2 different threads could read the initial value (0), operate (locally) on it (obtaining 1), then writing it to the main memory (both would end up writing 1) -- the 2 increments would be perceived as only 1.
To solve this, you must make the increment an atomic operation. To do so, you'd need to either use a synchronization mechanism -- a mutex (synchronized (...) { ... }, or an explicit lock) -- or a class designed specifically for this things: AtomicInteger.
volatile can make sharing safe (if atomicity of a single read or write operation is sufficient), it doesn't cause sharing.
Note that if you make d static, it is actually unspecified what value d would have, because the statement d = d + 1 is not atomic, i.e. a thread may be interrupted between reading and writing d. A synchronized block, or an AtomicInteger are the typical solutions for that.