Java synchronization and data consistency - java

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);

Related

synchronized keyword in Java threads

I am trying to see how multithreading(particularly with synchronized keyword) works.In this example I want the second thread abc1 to start executing after thread abc. So I've used synchronized keyword in run function.But the output line which says:
Initial balance in this thread is 10000
Initial balance in this thread is 10000
is what concerns me.Because the initial balance should be "-243000" as indicated in output line
Final balance after intial -243000 is 59049000
because the abc1 thread should wait for abc due to synchronized keyword.
Primarily , I want the threads to behave as if I write
abc.start
abc.join()
abc1.start()
abc1.join()
Here is my source code:
class parallel extends Thread{
account a;
public parallel(account a) {
this.a=a;
}
public synchronized void run() {
synchronized(this) {
System.out.println("Initial balance in this thread is "+a.amount);
long duplicate=a.amount;
boolean flag=true;
//System.out.println("Transaction inititated");
for(int i=0;i<10;i++) {
if(flag==true) {
//System.out.println("Deducting "+amount+"Rs from your account");
a.amount-=a.amount*2;
}
else {
//System.out.println("Depositing "+amount+"Rs from your account");
a.amount+=a.amount*2;
}
flag=!flag;
}
System.out.println("Final balance after intial "+duplicate+" is "+a.amount);
syncro.amount=a.amount;
}
}
}
class account{
public account(long rupe) {
amount=rupe;
}
long amount;
}
public class syncro {
static long amount;
public static void main(String[] args) throws InterruptedException{
//for(int i=0;i<10;i++) {
account ramesh=new account(1000);
parallel abc=new parallel(ramesh);
parallel abc1=new parallel(ramesh);
abc.start();
//abc.join();
abc1.start();
//abc1.join();
//}
//awaitTermination();
//Thread.sleep(4000);
boolean ab=true;
long cd=1000;
for(int i=0;i<10;i++) {
if(ab==true) {
//System.out.println("Deducting "+ab+"Rs from your account");
cd-=cd*2;
}
else {
//System.out.println("Depositing "+a+"Rs from your account");
cd+=cd*2;
}
ab=!ab;
}
//System.out.println("Final amount by multithreading is "+);
System.out.println("Final amount after serial order is "+cd);
}
}
You are mixing the creating of your own threads with the use of synchronized. Also, using synchronized(this) within a synchronized method is doing the same thing twice.
Synchronized is NOT about starting threads. It is about allowing only one thread to enter a certain block of code at a time.
Every object you create has a hidden field that you cannot read, but it does exist. It is of type Thread and it is called owner.
The synchronized keyword interacts with this hidden field.
synchronized (object) {
code();
}
means the following:
If object.owner == Thread.currentThread(), then just keep going and increment a counter.
If object.owner == null, then run object.owner = Thread.currentThread(), set that counter to 1, and keep going.
Otherwise (So, object.owner is some other thread), stop, freeze the thread, and wait around until the owner is set to null, and then we can go to option #2 instead.
Once we're in, run code(). When we get to the closing brace, decrement the counter. If it is 0, run object.owner = null.
Furthermore, all the above is done atomically - it is not possible for 2 threads to get into a race condition doing all this stuff. For example, if 2 threads are waiting for owner to become unset again, only one will 'get it', and the other will continue waiting. (Which one gets it? A VM impl is free to choose whatever it wants; you should assume it is arbitrary but unfair. Don't write code that depends on a certain choice, in other words).
A method that is keyworded with synchronized is just syntax sugar for wrapping ALL the code inside it in synchronized(this) for instance methods and synchronized(MyClass.this) for static methods.
Note that synchronized therefore only interacts with other synchronized blocks, and only those blocks for which the object in the parentheses is the exact same obj reference, otherwise none of this does anything. It certainly doesn't start threads! All synchronized does is potentially pause threads.
In your code, you've put ALL the run code in one gigantic synchronized block, synchronizing on your thread instance. As a general rule, when you synchronize on anything, it's public API - other code can synchronize on the same thing and affect you. Just like we don't generally write public fields in java, you should not lock on public things, and this is usually public (as in, code you don't control can hold a reference to you). So don't do that unless you're willing to spec out in your docs how your locking behaviours are set up. Instead, make an internal private final field, call it lock, and use that (private final Object lock = new Object();).

Is Java caching entire objects or only parts of objects? (Visibility Issues)

I was trying to intentionally create visibility issues with threads and I got unexpected results:
public class DownloadStatus {
private int totalBytes;
private boolean isDone;
public void increment() {
totalBytes++;
}
public int getTotalBytes() {
return totalBytes;
}
public boolean isDone() {
return isDone;
}
public void done() {
isDone = true;
}
}
public class DownloadFileTask implements Runnable {
DownloadStatus status;
public DownloadFileTask(DownloadStatus status) {
this.status = status;
}
#Override
public void run() {
System.out.println("start download");
for (int i = 0; i < 10_000; i++) { //"download" a 10,000 bytes file each time you run
status.increment(); //each byte downloaded - update the status
}
System.out.println("download ended with: " + status.getTotalBytes()); //**NOTE THIS LINE**
status.done();
}
}
//creating threads, one to download, another to wait for the download to be done.
public static void main(String[] args) {
DownloadStatus status = new DownloadStatus();
Thread t1 = new Thread(new DownloadFileTask(status));
Thread t2 = new Thread(() -> {
while (!status.isDone()) {}
System.out.println("DONE!!");
});
t1.start();
t2.start();
}
So, running this would create a visibility problem - the second thread wouldn't see the updated value since it had cached it before it got written back by the first thread - this causes an endless (while) loop, the second thread is constantly checking the cached isDone(). (at least that's how I think it works).
The thing I don't get is why this visibility problem stops happening when I comment out the line from the second code block that calls status.getTotalBytes().
From my understanding both threads start by caching the status object as-is, so the second thread should constantly check his cached value (and essentially not see the new value updated by the first thread).
Why is this line calling a method in the status object causing this visibility issue? (and more interestingly - why not calling it fixes it?)
What you call a "visibility problem" is actually a data race.
A single thread sees the effects of its operations in the order they are written. That is if you update a variable and then read it, you'll always see the updated value within that thread.
The effects of a thread's execution may be different when viewed from another thread. This is mainly related to the language and the underlying hardware architecture. The compiler may reorder instructions, delay memory writes while keeping values in registers, or the values may be kept in a cache before written to the main memory. Without an explicit memory barrier, the value in the main memory would not be updated. That's what you call the "visibility problem".
It is likely that there is a memory barrier in System.println. So when you execute that line, all updates up to that point will be committed to the main memory, and the other threads can see it. Note that without explicit synchronization, there is still no guarantee that the other threads will see it, because those threads may re-use the value they got for that variable before. There is nothing in the program that tells the compiler/runtime that the values may be changed by other threads.
This is the race condition between two threads. There is nothing to do with status.getTotalBytes() statement in your code. It is the scheduler that decides which thread will run. It is by chance that you are not getting stuck in the infinit loop after commenting the println statement. The main problem in your code that increment and set status should be atomic operation and replace the definition of run method as below. Secondly increment is also not a atomic operation. You can unpredictable results if there is no proper synchronization.
#Override
public void run() {
System.out.println("start download");
incrementAndSetStatus();
}
public synchronized void incrementAndSetStatus(){
for (int i = 0; i < 100000; i++) { //"download" a 10,000 bytes file each time you run
status.increment(); //each byte downloaded - update the status
}
System.out.println("download ended with: " + status.getTotalBytes()); //**NOTE THIS LINE**
status.done();
}

Is this code not thread safe?

I was expecting this code to be thread safe. I ran it a few times, but got different results. However, if I uncomment the sleep(1000) part, it prints 10000 every time (at least from the results from my test runs).
So what's wrong? Could it be something to do with thread.join()?
public class Test implements Runnable{
private int x;
public synchronized void run(){
x++;
}
public static void main(String args[]){
Test test = new Test();
Thread thread = null;
for (int i = 0; i < 10000; i++) {
thread = new Thread(test);
try {
thread.join();
} catch (InterruptedException e) {}
thread.start();
}
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println(test.x);
}
}
edit: oops, my bad. I misunderstood how Thread#join functions. And synchronizing on run() method is a bad idea.
thread.join() should be called after thread.start().
join() means "block until the thread finishes". That only makes sense after the thread has started.
Presumably your Thread.sleep() call actually waits long enough for all the threads (that you effectively didn't join) to finish. Without it, the threads might not all have finished when you print out the value of x.
There are two problems here:
a race condition where the main thread finishes before all the worker threads.
a memory visibility issue where the main thread is not guaranteed to see the updated value of x.
Thread#join is implemented using Object#wait. The condition variable used is the alive flag on the Thread:
groovy:000> new Thread().isAlive()
===> false
Thread.join is checking the alive flag before the thread has started, so isAlive returns false and join returns before the thread can start. The counter still gets incremented eventually, but since the join doesn't happen for that thread then the main thread may be printing out the results for x before all the threads can execute.
Adding the sleep gives all the threads enough time to finish up that x is what you expect by the time that the main thread prints it out.
In addition to the race condition, there is a memory visibility issue since the main thread is accessing x directly and is not using the same lock as the other threads. You should add an accessor to your Runnable using the synchronized keyword:
public class Test implements Runnable{
private int x;
public synchronized void run(){
x++;
}
public synchronized int getX() {
return x;
}
and change the main method to use the accessor:
System.out.println(test.getX());
Memory visibility issues may not be apparent since they depend on how aggressive the JVM is about caching and optimizing. If your code runs against a different JVM implementation in production, and you don't adequately guard against these issues, you may see errors there that you can't reproduce locally on a PC.
Using AtomicInteger would simplify this code and allow solving the memory visibility problem while removing synchronization.
You don't add synchronized to the run method. Each thread gets its own.
You have to synchronize the mutable, shared data. In your case, that's the integer x. You can synchronize get/set or use AtomicInteger.

Thread synchronization- When does a thread release the lock on an object

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!

Java synchronized keyword issue

I am trying to understand the keyword synchronized from the following example
Java Main Method -->
public int methodA(){
Hello h = new Hello();
h.callSomeSynchronizedMethod();
sysout("Main");
return 0;
}
In the Hello Class-->
public synchronized void callSomeSynchronizedMethod(){
Hi h = new Hi();
h.someMethod();
sysout("Hello");
}
In the Hi class
public void someMethod(){
sysout("Hi");
}
So what would be the list of outputs that i will get;
1.) Is it in the order of Hi, Hello and Main ?
2.) What i understand about the synchronized keyword is that it will only execute 1 method and then execute the other, without multi-threading. Is this correct ?
To really understand what synchronized does you need to run the program twice, once synchronized and once not. Also your program should use multiple threads. So here is an example of such a test.
public class Synchro {
public static void main(String args[]){
new Synchro();
}
public Synchro(){
final Moo moo = new Moo();
Thread t = new Thread(new Runnable(){
public void run(){
moo.aMethod("Second");
}
});
t.start();//calling the method in a thread
moo.aMethod("First");//calling the same method from the same object in the main thread
}
class Moo{
public Moo(){
}
public void aMethod(String name){
//this loop just prints slowly so you can see the execution
for(int i = 1; i <= 100; i++){
System.out.println(String.format("%s : %d", name, i));
try{
Thread.sleep(50);
}catch(InterruptedException e){}
}
}
}
}
Now, if you run the above code, noticing that the method is not synchronized, you will see the printout from the two executions of the method interleaved. That is you will see First 1 then Second 1 then First 2 etc.
Now, add the synchronized keyword to the method making it:
public synchronized void aMethod(String name){ ....
and run the code again. This time, one execution of the method completes before the other begins.
The synchronized keyword is only necessary when multiple threads are accessing the very same object.
You would get "Hi", then "Hello", then "Main", yes. The synchronized modifier has nothing to do with the order the methods are called in; and, other than adding a bit of overhead, it does nothing at all when running the code in a single thread. You could run this same test without synchronized and get the same result.
Now, if you ran a similar test where multiple threads were calling these methods, your results would be less determinate.
Synchronized is meant to allow for the more safe execution of code and management of resources in a multi-threaded environment.
http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Hope this helps.
all these methods will be executed in one thread so the answer for the first question is "yes".
synchronized keyword emans that the method can be executed in only one thread at every moment of time. So if you call it from another thread - it will wait till the execution is finished in the first thread.
In Java there is no automatic multithreading: you must explicitly start a thread and pass it a run method that it will execute. Only in that case will the synchronized keyword start to matter, but its meaning is not quite as you understand it: the methods will execute in whatever thread calls them, but while one is executing, another thread will block before it is able to execute a method guarded by the same lock.

Categories

Resources