I have doubt in the behaviour of volatile keyword.
public class TestClassI extends Thread {
private volatile int i=5;
boolean flag;
public TestClassI( boolean flag) {
this.i=i;
this.flag=flag;
}
public void run()
{
if(flag)
{
while(true)
{
System.out.println(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
else
{
i=10;
}
}
}
and in main class using as
public class TestMain {
public static volatile int i=5;
public static void main(String args[]) throws InterruptedException
{
TestClassI test= new TestClassI( true);
test.start();
Thread.sleep(1000);
TestClassI test2=new TestClassI( false);
test2.start();
}
}
I expected the value will be like
5
5
5
5
10
10
10
10.
But it is keep on giving 5. But asper nature of volatile value of i should be stored and retrieved from main memory each time. Please explain is there anything wrong in this code?
You have two instances of TestClassI. They each have their own version of i (because it is an instance field). They don't interfere at all with eachother.
The static TestMain.i is not used in the program at all. There is no shared state.
When the object is instantiated with a false flag, the run method initializes i to 10, and returns. i is never printed:
if (flag) {
// irrelevant
}
else {
i = 10;
}
You don't set i=10in your loop, so it will be set as the only action in your thread, but never printed...
volatile variables have no effect in this case because the variable is an int. long and double variables are affected by volatile, they are loaded and stored in one operation that can't be interrupted rather than two, one for each word. So the volatile variables have no effect.
What is happening that produces the unusual output is that the i is not shared among your threads. If you look, there is a separate i for each thread, although there is a static i in the main class. FYI, the i in the main class is left unnoticed by the threads, who don't notice it at all. If you'd like it to work, one simple modification will suffice: make the i variable in the thread static. Not in the main class, in the thread.
Related
I am using jdk1.8.
This code runs directly into an infinite loop, but if I add the commented code, it will run normally. I have tried a lot of codes, as long as the operation of locking is involved, it can run normally.
public class StateTest {
public static void main(String[] args) {
State state = new State();
new Thread(new Work(state)).start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
state.setStart(true);
System.out.println("the main thread is finished");
}
static class State {
private boolean isStart = false;
public boolean isStart() {
return this.isStart;
}
public void setStart(boolean start) {
this.isStart = start;
}
}
static class Work implements Runnable {
private State state;
public Work(State state) {
this.state = state;
}
#Override
public void run() {
int i = 0;
//endless loop
while (!this.state.isStart()) {
i++;
// if open this code,it will be ok
// synchronized (this) {
//
// }
}
System.out.println(String.format("work start run after %s loops", i));
}
}
}
The problem is that a State instance is not thread-safe. If one thread calls setStart and a second thread calls isStart, then the second thread may not see the value that the first one set1.
You are using setStart on a State instance so that one instance can signal a second one to end the loop. If the second thread doesn't see the state change (because of the above) then the loop won't terminate2.
Solutions:
Change setStart and isStart to be synchronized methods.
Declare the isStart field to be volatile.
Instead of writing your own State class, use a standard java.util.concurrent class to do the synchronization; e.g. CountDownLatch (javadoc).
I recommend that you take the time to study the Oracle Java Tutorial Lesson on concurrency:
The Java™ Tutorials: Lesson: Concurrency
1 - The technical explanation for why this can happen is set out in the "Java Memory Model" section of the Java Language Specification. However, the JLS is NOT written in a way that beginners can understand, and that part is particularly difficult.
2 - In fact, the JLS doesn't say whether the change will be seen or not seen. The actual behavior is liable to depend on a range of factors that are outside of the programmer's control.
It is not guaranteed the isStart value update is visible in the newly created thread.
Since multiple threads access the isStart field, you want to mark it as volatile to assure the updated variable value will be written always in the main memory and not the CPU cache.
static class State {
private volatile boolean isEnd = false;
// getters & setters
}
I have the following piece of code
Boolean flag = new Boolean(false);
flag = true;
Will the second line (assignment) cause a recreation of the initial object (basically a call to new()) in the JVM? I am asking because I am using a Boolean object to synchronize multiple threads, and I am afraid that if a re-initialization takes places, the waiting threads will not see the change in value.
In my application, there are multiple threads that are given a reference to the previous Boolean object. Only one thread changes the objects value to true, and the rest wait until the object's value becomes true. So, if T1 is the thread that changes the value, its code is like:
synchronized(flag) {
flag = true;
flag.notifyAll();
}
and the rest of the threads (T2) will have code like:
synchronized(flag) {
while(flag == false)
wait();
if(flag == true) {
//do something
}
}
Therefore, the question is that after the assignment of true to flag, will the other threads (T2) still have access to the original object?
Thanks,
Nick
The assignment flag = false is a boxing conversion. It will get compiled as flag=Boolean.valueOf(false) which will end up returning the constant Boolean.FALSE.
So the answer is, it will not create a new object but it will change the variable flag as it assigns an instance distinct from your previous result of new Boolean(false).
It’s not quite clear what you are actually doing but in general, synchronizing on a mutable variable is broken design.
The problem is that you are mixing the value that makes up your condition and the object to synchronize on. The simplest implementation of your updated intention is to use a simple boolean flag and synchronize on the instance that contains the flag:
class WithFlag {
private boolean flag;
public synchronized void setToTrue() {
if(!flag) {
flag=true;
notifyAll();
}
}
public synchronized void waitForTrue() throws InterruptedException {
while(!flag) wait();
}
}
Note that declaring an instance method synchronized is similar to wrap its code with synchronized(this) { … }
If you want to use a boolean to synchronize threads, you should consider using AtomicBoolean, which is specifically designed for this purpose.
The other answers have already explained that when you say flag=false, it is a boxing conversion which will return the constant Boolean.FALSE. One important point that the other answers have covered but not emphasized on is that when you obtain a lock on two Boolean objects that were assigned the same value through a boxing conversion, it is as good as obtaining a lock on one Boolean object.
My answer attempts to give an example to explain this. Consider the following code that creates two threads that obtain a lock on a Boolean.
public class BooleanTest {
public static void main(String[] args) {
BooleanTest test = new BooleanTest();
test.booleanTest();
}
private void booleanTest() {
BooleanLockTester booleanLock1 = new BooleanLockTester();
booleanLock1.setBooleanLock(true);
BooleanLockTester booleanLock2 = new BooleanLockTester();
booleanLock2.setBooleanLock(true);
BooleanLocker booleanLocker1 = new BooleanLocker(booleanLock1);
BooleanLocker booleanLocker2 = new BooleanLocker(booleanLock2);
Thread threadOne = new Thread(booleanLocker1);
Thread threadTwo = new Thread(booleanLocker2);
threadOne.start();
threadTwo.start();
}
private class BooleanLocker implements Runnable {
private BooleanLockTester booleanLockObj;
public BooleanLocker(BooleanLockTester booleanLockObj) {
this.booleanLockObj = booleanLockObj;
}
#Override
public void run() {
booleanLockObj.testLockOnBoolean();
}
}
private class BooleanLockTester {
private Boolean booleanLock = false;
public synchronized void testLockOnBoolean() {
synchronized (booleanLock) {
for (int i = 0; i<1000000000; ++i) {
System.out.println(Thread.currentThread().getName());
}
}
}
public void setBooleanLock(Boolean booleanLock) {
this.booleanLock = booleanLock;
}
}
}
In the above example, the two threads will never be able to enter the for loop together. When you run the program, you will see that the thread that starts first will start printing on the console and only when it is finished, the next thread will start printing to the console.
Let's make a small change in the above code :
Change the following line in the code :
booleanLock2.setBooleanLock(true);
To this :
booleanLock2.setBooleanLock(false);
You will now see that the threads stop behaving and print to the console in a random order. This is because the threads now obtain a lock on two different objects.
im trying to write a program in which two threads are created and the output should be like 1st thread prints 1 and the next thread prints 2 ,1st thread again prints 3 and so on. im a beginner so pls help me clearly. i thought thread share the same memory so they will share the i variable and print accordingly. but in output i get like thread1: 1, thread2 : 1, thread1: 2, thread2 : 2 nd so on. pls help. here is my code
class me extends Thread
{
public int name,i;
public void run()
{
for(i=1;i<=50;i++)
{
System.out.println("Thread" + name + " : " + i);
try
{
sleep(1000);
}
catch(Exception e)
{
System.out.println("some problem");
}
}
}
}
public class he
{
public static void main(String[] args)
{
me a=new me();
me b=new me();
a.name=1;
b.name=2;
a.start();
b.start();
}
}
First off you should read this http://www.oracle.com/technetwork/java/codeconventions-135099.html.
Secondly the class member variables are not shared memory. You need to explicitly pass an object (such as the counter) to both objects, such that it becomes shared. However, this will still not be enough. The shared memory can be cached by the threads so you will have race-conditions. To solve this you will need to use a Lock or use an AtomicInteger
It seems what you want to do is:
Write all numbers from 1 to 50 to System.out
without any number being printed multiple times
with the numbers being printed in order
Have this execution be done by two concurrent threads
First, let's look at what is happening in your code: Each number is printed twice. The reason for this is that i is an instance variable of me, your Thread. So each Thread has its own i, i.e., they do not share the value.
To make the two threads share the same value, we need to pass the same value when constructing me. Now, doing so with the primitive int won't help us much, because by passing an int we are not passing a reference, hence the two threads will still work on independent memory locations.
Let us define a new class, Value which holds the integer for us: (Edit: The same could also be achieved by passing an array int[], which also holds the reference to the memory location of its content)
class Value{
int i = 1;
}
Now, main can instantiate one object of type Value and pass the reference to it to both threads. This way, they can access the same memory location.
class Me extends Thread {
final Value v;
public Me(Value v){
this.v = v;
}
public void run(){
for(; v.i < 50; v.i++){
// ...
}
public static void main(){
Value valueInstance = new Value();
Me a = new Me(valueInstance);
Me b = new Me(valueInstance);
}
}
Now i isn't printed twice each time. However, you'll notice that the behavior is still not as desired. This is because the operations are interleaved: a may read i, let's say, the value is 5. Next, b increments the value of i, and stores the new value. i is now 6. However, a did still read the old value, 5, and will print 5 again, even though b just printed 5.
To solve this, we must lock the instance v, i.e., the object of type Value. Java provides the keyword synchronized, which will hold a lock during the execution of all code inside the synchronized block. However, if you simply put synchronize in your method, you still won't get what you desire. Assuming you write:
public void run(){ synchronized(v) {
for(; v.i < 50; v.i++) {
// ...
}}
Your first thread will acquire the lock, but never release it until the entire loop has been executed (which is when i has the value 50). Hence, you must release the lock somehow when it is safe to do so. Well... the only code in your run method that does not depend on i (and hence does not need to be locking) is sleep, which luckily also is where the thread spends the most time in.
Since everything is in the loop body, a simple synchronized block won't do. We can use Semaphore to acquire a lock. So, we create a Semaphore instance in the main method, and, similar to v, pass it to both threads. We can then acquire and release the lock on the Semaphore to let both threads have the chance to get the resource, while guaranteeing safety.
Here's the code that will do the trick:
public class Me extends Thread {
public int name;
final Value v;
final Semaphore lock;
public Me(Value v, Semaphore lock) {
this.v = v;
this.lock = lock;
}
public void run() {
try {
lock.acquire();
while (v.i <= 50) {
System.out.println("Thread" + name + " : " + v.i);
v.i++;
lock.release();
sleep(100);
lock.acquire();
}
lock.release();
} catch (Exception e) {
System.out.println("some problem");
}
}
public static void main(String[] args) {
Value v = new Value();
Semaphore lock = new Semaphore(1);
Me a = new Me(v, lock);
Me b = new Me(v, lock);
a.name = 1;
b.name = 2;
a.start();
b.start();
}
static class Value {
int i = 1;
}
}
Note: Since we are acquiring the lock at the end of the loop, we must also release it after the loop, or the resource will never be freed. Also, I changed the for-loop to a while loop, because we need to update i before releasing the lock for the first time, or the other thread can again read the same value.
Check the below link for the solution. Using multiple threads we can print the numbers in ascending order
http://cooltekhie.blogspot.in/2017/06/#987628206008590221
I am trying to understand Synchornized in Java.
I understood if I have access a synchronized method on same object from 2 different Threads, only one will be able to access at a time.
But I think if the same method is being called on 2 different instances, Both Objects should be able to access the method parallel. Which would cause race condition if accessing/modifying a static member variable from the method. But I am not able to see the race condition happening in below code.
Could someone please explain whats wrong with the code or my understanding.
For reference code is accessible at : http://ideone.com/wo6h4R
class MyClass
{
public static int count=0;
public int getCount()
{
System.out.println("Inside getcount()");
return count;
}
public synchronized void incrementCount()
{
count=count+1;
}
}
class Ideone
{
public static void main(String[] args) throws InterruptedException {
final MyClass test1 = new MyClass();
final MyClass test2 = new MyClass();
Thread t1 = new Thread() {
public void run()
{
int k=0;
while (k++<50000000)
{
test1.incrementCount();
}
}
};
Thread t2 = new Thread() {
public void run()
{
int l=0;
while (l++<50000000)
{
test2.incrementCount();
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
//System.out.println(t2.getState());
int x=500000000+500000000;
System.out.println(x);
System.out.println("count = " + MyClass.count);
}
}
You're right that the race condition exists. But the racy operations are so quick that they're unlikely to happen -- and the synchronized keywords are likely providing synchronization "help" that, while not required by the JLS, hide the races.
If you want to make it a bit more obvious, you can "spell out" the count = count + 1 code and put in a sleep:
public synchronized void incrementCount()
{
int tmp = count + 1;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count=tmp;
}
That should show the races more easily. (My handling of the interrupted exception is not good for production code, btw; but it's good enough for small test apps like this.)
The lesson learned here is: race conditions can be really hard to catch through testing, so it's best to really understand the code and prove to yourself that it's right.
Since syncrhonized methods actually synchronize on this different instance methods will lock on different objects and therefore you will get race conditions since they don't block each other.
You probably have to make your own lock object and lock on that.
class MyClass
{
public static int count=0;
//this is what you lock on
private static Object lock = new Object();
public int getCount()
{
synchronized(lock){
System.out.println("Inside getcount()");
return count;
}
}
public void incrementCount()
{
synchronized(lock){
count = count+1;
}
}
//etc
Now when you run your main, this gets printed out:
1000000000
count = 100000000
Here's the relevant section of the Java specification:
"A synchronized method acquires a monitor (§17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used."
However I fail to see where the MyClass' instances are actually incrementing "count" so what exactly are you expecting to show as a race condition?
(Taken originally from this answer)
I can't Seem to get a final counter value Of 20000. What is wrong with this code?
public class Synchronize2 {
public static void main(String[] args) {
Threading t1 = new Threading();
Threading t2 = new Threading();
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Threading.counter);
}
}
class Threading extends Thread {
static int counter;
public synchronized void incrementer() {
counter++;
}
public void run() {
for (int i=0; i<10000; i++) {
incrementer();
}
}
}
Your synchronized incrementer method will lock on the object itself. But you have 2 different objects, each locking on themselves, so the method isn't thread safe; both threads can still access incrementer at the same time.
Additionally, the post-increment operation isn't thread safe because it's not atomic; there is a read operation and an increment operation, and a thread can be interrupted in the middle of the two operations. This non-thread-safe code presents a race condition, where thread one reads the value, thread two reads the value, then thread one increments and thread two increments, yet only the last increment "wins" and one increment is lost. This shows up when the ending value is less than 20000.
Make the method static too, so that because it's synchronized, it will lock on the class object of the class, which is proper synchronization here.
public static synchronized void incrementer() {
You synchronize on two different Objects. Your incrementer is a short form of this:
public void incrementer() {
synchronized (this) {
counter++;
}
}
But the two instances of "this" are not the same Object. Thus, you do not synchronize at all. Try it this way:
private static Object sync = new Object();
public void incrementer() {
synchronized (sync) {
counter++;
}
}
You should also make the variable counter volatile. It is not strictly neccessary here, because you use it only in synchronized blocks. But in real code you might read it outside such a block, and then you will get problems. Non volatile variables can be read from a local thread cache, instead from the memory.