I've a question about synchronization in java. In the following Java program I dont get any output. But, if I remove the synchronized statement from the method IFoo.s() I'll get some output. It seems like the methods IFoo.setP() and IFoo.s() are synchronized among each other. But 'synchronized' should only prevent that two threads call the synchronized method at the same time, right?
package com.example.relectiontest;
import java.awt.Point;
import java.util.Random;
public class Main {
public static void main(String[] args) throws Exception{
final IFoo f = new IFoo();
Runnable r = new Runnable() {
public void run() {
Random r = new Random();
int a = r.nextInt(5)+1;
for(int i=0;i<1000000;++i){
f.setP(a);
}
}
};
Runnable r2 = new Runnable() {
public void run() {
for(int i=0;i<1000000;++i){
f.s();
}
}
};
Thread T1 = new Thread(r, "T1");
Thread T2 = new Thread(r, "T2");
Thread T3 = new Thread(r2, "T3");
T3.start();
T1.start();
T2.start();
}
private static class IFoo{
private Point p = new Point();
public synchronized void setP(int a){
//System.out.println("p1 "+Thread.currentThread());
p.x = a;
p.y = p.x;
int x = p.x , y = p.y;
if(x != y)
System.out.println(Thread.currentThread()+"\t"+x+" "+y);
//System.out.println("p2 "+Thread.currentThread());
}
public synchronized void s(){
//System.out.println("s");
p.x = 0;
}
}
}
So, why I cant see any output?
regards
Because thanks to synchronization x != y will never be true.
In your unsynchronized version s() has the chance of setting p.x to 0 every once in a while (even though it's not synchronized properly).
In the synchronized version s() must wait until setP is finished (since they're both synchronized, sharing the implicit this lock), and thanks to the logic in setP the condition can not be true.
Your example is overly complex. You can write it out as follows (adding synchronized on both methods to see that nothing will be printed):
private static class IFoo {
volatile int x = 0;
public void setP(int a) {
x = a;
if(x != a)
System.out.println("Someone changed x!");
}
public void s() {
x = 0;
}
}
Also note that static synchronized methods synchronize on the Class object since they have no this. Instance and static methods therefore won't lock each other unless you explicitly synchronize on a common lock.
In Java all synchronized calls are synchronized on an object. For instance methods, they object is the class instance - so in your case setP and s are both synchronized on the instance of IFoo.
This allows you to control access to shared fields which are accessed through more than one method. With your code, this will be exactly what you need - you need to make sure you don't have one thread in setP changing the state while another in s is reading it.
If you prefer finer control you can use synchronized blocks, which allow you to specify the object to lock on:
private final Object o=new Object();
public void method(){
synchronized (o){
//Synchronized code
}
}
This is the generally generally recommended approach - it allows you to encapsulate your lock, so you don't risk some other class interfering with your locks and potentially DOSing your code.
Static methods are synchronized on the class object (such as IFoo.class).
From documentation:
making these methods synchronized has two effects:
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.
The output will be displayed only when:
if(x != y)
Because in lines:
p.x = a;
p.y = p.x;
int x = p.x , y = p.y;
You make x == y that output is not displayed.
When you remove synchronization keyword from s method - the threads sometimes set x to 0 and this make if(x != y) - to true. and output is visible.
Because normally you shouldn't get any output as x should be equal to y.
However, when you remove the synchronized keyword, two threads execute at the same time and you may get an output if s() executes between p.y=p.x and x=p.x statements.
Related
Let's say I have the following code in Java
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
}
And I create two threads T1 and T2
Thread T1 = new Thread(c1);
Thread T2 = new Thread(c2);
Where c1 and c2 are two different instances of the class SynchronizedCounter.
It is really needed to synchronize the method increment? Because I know that when we use a synchronized method, the thread hold a lock on the object, in this way other threads cannot acquire the lock on the same object, but threads "associated" with other objects can execute that method without problems. Now, because I have only one thread associated with the object c1, it is anyway needed to use the synchronized method? Also if no other threads associated with the same object exist?
In your specific example, synchronized is not needed because each thread has its own instance of the class, so there is no data "sharing" between them.
If you change your example to:
Thread T1 = new Thread(c);
Thread T2 = new Thread(c);
Then you need to synchronize the method because the ++ operation is not atomic and the instance is shared between threads.
The bottom line is that your class is not thread safe without synchronized. If you never use a single instance across threads it doesn't matter. There are plenty of legitimate use cases for classes which are not thread safe. But as soon as you start sharing them between threads all bets are off (i.e. vicious bugs may appear randomly).
Given code/example does not need synchronization since it is using two distinct instances (and so, variables). But if you have one instance shared between two or more threads, synchronization is needed, despite comments stating otherwise.
Actually it is very simple to create a program to show that behavior:
removed synchronized
added code to call the method from two threads
public class SynchronizedCounter {
private int c = 0;
public void increment() {
c++;
}
public static void main(String... args) throws Exception {
var counter = new SynchronizedCounter();
var t1 = create(100_000, counter);
var t2 = create(100_000, counter);
t1.start();
t2.start();
// wait termination of both threads
t1.join();
t2.join();
System.out.println(counter.c);
}
private static Thread create(int count, SynchronizedCounter counter) {
return new Thread(() -> {
for (var i = 0; i < count; i++) {
counter.increment();
}
System.out.println(counter.c);
});
}
}
Eventually (often?) this will result in weird numbers like:
C:\TMP>java SynchronizedCounter.java
122948
136644
136644
add synchronized and output should always end with 200000:
C:\TMP>java SynchronizedCounter.java
170134
200000
200000
Apparently posted code is not complete: the incremented variable is private and there is no method to retrieve the incremented value. impossible to really know if the method must be synchronized or not.
I use 2-dimensional array in Java. But now, I want to use this class for multi-thread. How can I do that?
I know that how can I do a thread safe function (add synchronized keyword). What happens if clear and getItem functions are triggered at the same time? How can I do thread safe inctance for this case?
public class ThreadSafeArray {
int ROW_MAX_COUNT = 1024;
int rowCount = 0;
int counterForRow = 0;
private Object [][] objInstances = new Object[ROW_MAX_COUNT][];
public synchronized void addItem(Object obj) {
if(counterForRow == ROW_MAX_COUNT) {
objInstances[++rowCount] = new Object[ROW_MAX_COUNT];
counterForRow = 0;
}
objInstances[rowCount][counterForRow++] = obj;
}
public synchronized void clear() {
objInstances = new Object[ROW_MAX_COUNT][];
rowCount = 0;
counterForRow = 0;
}
public synchronized Object getItem(int index) {
int row = index / ROW_MAX_COUNT;
int column = index % ROW_MAX_COUNT;
if((row <= rowCount) && (column <= counterForRow)) {
return objInstances[row][column];
}
return null;
}
}
IN your code, clearand getItem are instance methods. Putting synchronized on an instance method means that the thread has to acquire the lock (the "intrinsic lock") on the object instance that the method is called on before the thread can start executing any code in that method.
Making instance methods synchronized has two effects(from java guide):
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.
So,your class is already thread-safe for these two methods.
What happens if clear and getItem functions are triggered at the same time?
One will wait until another is finished.
How can I do thread safe inctance for this case?
It is already thread-safe.
I have a sample class:
public class LocksAndSynchronization {
private Object lock1 = new Object();
private Object lock2 = new Object();
static int count;
public void methodOne() {
for (int i = 1; i <= 10000; i++) {
count++;
}
}
public void methodTwo() {
for (int i = 1; i <= 10000; i++) {
count++;
}
}
public synchronized void process() {
methodOne();
methodTwo();
}
public static void main(String[] args) throws InterruptedException {
final LocksAndSynchronization l = new LocksAndSynchronization();
Thread t1 = new Thread() {
#Override
public void run() {
l.process();
}
};
Thread t2 = new Thread() {
#Override
public void run() {
l.process();
}
};
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("count: " + count);
}
}
process() actually makes a call to both the methods. So which is a better approach?
Synchronize methodOne and methodTwo or,
Synchronize process() (as done in the code above) ?
Both of the above options would work. But which of them makes more sense?
count is static, so it is same for all object. so you need to syncronize process static way. to do that, create a static lock and use it
static Object staticObject = new Object();
public void process() {
synchronized( staticObject){
methodOne();
methodTwo();
}
}
or you can synronize methodOne and methodTwo
static Object staticObject = new Object();
public void methodOne() {
synchronized( staticObject){
for (int i = 1; i <= 10000; i++) {
count++;
}
}
}
public void methodTwo() {
synchronized( staticObject){
for (int i = 1; i <= 10000; i++) {
count++;
}
}
}
moreover, using synchronize keyword in function declaration, it means using object itself as lock. so, if you have multiple object, you block is synchronized according to object.
I would prefer to synchronize methodOne and methodTwo since they may be called from outside the object. They also can be called without being embedded in process. Therefore each method should be implemented in a threadsafe manner on its own.
Hope that helped.
Your simplified code doesn't make it easy to discern the essence of your question. For one, count is static so locking at instance level can't work, but that could just be a distractor.
A more important consideration are methodOne and methodTwo, two public methods which apparently require synchronization, but do none on their own. If you choose to synchronize just the process method, that means that you are requiring all the other callers of methodOne and methodTwo to take proper care of synchronization as well, which looks like quite shaky design.
Moreover, if you don't need the entire process to be atomic, and it can decompose into two separate atomic steps, then again it is more natural to have locking follow those semantics. This depends on whether you'll be calling methodOne and methodTwo from aynwhere else in your program.
It is advisable to synchronize as little piece of code as possible, because it generates contentions (other threads waiting). Therefore approach no 1 is preferable.
No matter whether you synchronize process or any of the methods separately, you still will not have consistency between method1 and method2 (i.e. that the variable count would not be changed between these calls). The reason is that the variable count is static, so it's not thread-safe even though it's used from within a synchronized method.
As Adem says, the static 'count' field needs a static lock. However there is a bigger interface design concern here. Both methodOne and methodTwo are public meaning that that they can be called from any other class. If they are required to execute in a synchronised context then it's advisable that they both utilise the synchronisation mechanism.
If it were not the case that methodOne and methodTwo were public, my preference would be to perform the syncrhonisation at the higher level (because this is slightly more efficient and flexible), i.e. in the process method, and then to put a comment on the other two methods which specifies that they must be called from a synchronized context.
I saw this on Java's synchronization tutorial:
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
The tutorial says that subsequent calls by different threads block, like so:
A: increment();
B: increment(); <-- has to wait for A to finish
...but say two threads interleave like so:
A: increment(): load c -> 0;
B: decrement(): load c -> 0;
A: increment(): increment c -> 1;
B: decrement(): decrement c -> -1;
A: increment(): save c -> 1;
B: decrement(): save c -> -1;
Finally: c == -1;
Neither has to wait, in my understanding of the tutorial; so is c protected from memory inconsistency?
Due to popular demand: the tutorial
The synchronized keyword on a (non-static) method causes the method to lock on the enclosed object - in this case the instance of SynchronizedCounter. Thus each synchronized method prevents each other synchronized method from running in another thread. So in your example, thread A's call to increment() would complete before thread B's call to decrement() would start. Therefore your class is thread safe.
Your current understanding of Java threading is not complete. In Java, every object has an "implicit lock", which is the object itself. And the "synchronized" keywords uses this implicit lock to make your code thread safe. The following code has the same effect:
public class SynchronizedCounter {
private int c = 0;
public void increment() {
synchronized(this){
c++;
}
}
public void decrement() {
synchronized(this){
c--;
}
}
public int value() {
synchronized(this){
return c;
}
}
}
Also, if you want to, you can declare multiple objects to server as simple lock objects. This, again, has the same effect:
public class SynchronizedCounter {
private int c = 0;
private Object lockObject;
public void increment() {
synchronized(lockObject){
c++;
}
}
public void decrement() {
synchronized(lockObject){
c--;
}
}
public int value() {
synchronized(lockObject){
return c;
}
}
}
Before synchronized method or synchronized block (also sometimes called guarded block) is executed, the executing thread must first obtain the lock. When it doesn't, the code in synchronized methods/block won't be executed. That's why your example will always work, because all the methods share one lock (the implicit one), none of the methods can be executed simultaneously with other methods.
For advanced locking mechanisms, please see the Lock interface.
Yes, c is protected from memory inconsistency.
However if the value of c is copied out of the object via the getter method, then that copy will live separately and become out of date.
None of the methods on SynchronizedCounter can be invoked simultaneously because they are all declared synchronised.
This does two things, firstly it creates a mutually exclusive region by requiring any thread to enter a monitor (http://en.wikipedia.org/wiki/Monitor_%28synchronization%29) and secondly it places memory barriers (http://en.wikipedia.org/wiki/Barrier_%28computer_science%29) at the entry to the method and the exit.
Thus only one thread can modify c at a time, and no matter which thread on which CPU core is executing that method then it will read the latest value of c and will make its change to c visible to the next thread that enters the monitor. For more on the memory barrier side, Doug Lea wrote a very useful guide at http://gee.cs.oswego.edu/dl/jmm/cookbook.html.
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)