I am studying Java concurrency right now. I have a question about synchronized and locks.
For any mutable data, we should put all the method accessing the data in the same lock.
But, what does same lock mean?
Example:
public class SynchronizedInteger{
private int value;
public synchronized int get(){return value;}
public synchronized void set(int value){this.value=value;}
}
So, my question is why this two methods are in the same lock? I know they are, but I would like to know why? And, does it mean that all the synchronized methods in the class are in the same lock?
Edit:
so, if I added one more method to the class:
public synchronized void printOneToHunder(){
for(int i=0;i<100;i++) System.out.println(i);
}
This method will also be included into same block as setter and getter? So, other thread cannot run this method when there is one thread using either setter or getter?
And, what if I change the class to below:
public class SynchronizedInteger{
private int value1;
private int value2;
public synchronized int get1(){return value1;}
public synchronized void set1(int value){this.value1=value1;}
public synchronized int get2(){return value2;}
public synchronized void set2(int value){this.value2=value2;}
}
For my understanding right now, only one thread can call these method at one time. So what's the way to make one thread can modify value1 and the other thread to modify value2???
Thanks a lot for your kindly clarifications!!!!
All non-static methods that you declare synchronized behave essentially as if the code was:
public synchronized int get() {
synchronized(this) {
// the method code
}
}
i.e. there is an implicit lock on this taken. So all non-static synchronized methods will lock the instance on which they are called.
Static synchronized methods take a lock on the class object itself, rather than an instance of that class.
Yes, your two methods are using the same lock.
The synchronized keyword without parameter is implicitly translated to syncrhonized(this), which is the same object for both methods.
In order for two blocks to have "the same lock" in java, it means that they are both using the same object as a lock. And as I said, in your case, both methods are using this as the lock object.
When you declare a method synchronized, it means that synchronization is on the particular instance for which the method is being invoked.
But you have other ways for synchronization.
Synchronized blocks:
synchronized(someLockedObj){somecode}
Lock-Objects:
Lock lock = new ReentrantLock(); lock.lock(); lock.unlock();
Related
I have seen usage of synchronized block by this so far but recently I learned that using dummy object is preferable. I found the following topic related to this.
Java synchronized method lock on object, or method?
As a summary, in the code below, two different object can not run addA and addB concurrently as both uses this for lock.
private int a;
private int b;
public synchronized void addA(){
a++;
}
public synchronized void addB(){
b++;
}
I am confused if I use dummy object for lock, what will be different if I use the line below in both method to synchronize? Because still they would have same lock.
synchronized(dummyObject){
...
}
So what it means that I should have two different dummy object for each method to use with sycnhronized as?
public void addA(){
synchronized(dummyObj1){
a++;
}
}
public void addB(){
synchronized(dummyObj2){
b++;
}
}
That is exactly the point of lock objects - you can use different locks for different operations. Assuming it makes sense to run addA and addB concurrently (and from the looks of it - it definitely does), you should indeed have two separate locks, one for each method.
You are correct. In this case you need two different objects to synchronize on them separately.
For locking purpose the easiest way is to create Object objects.
Object lock1 = new Object();
Object lock2 = new Object();
class ThreadSafeClass extends Thread
{
private static int count = 0;
public synchronized static void increment()
{
count++;
}
public synchronized void decrement()
{
count--;
}
}
Can anyone explain why above class is not thread safe?
Since the increment method is static it will synchronize on the class object for the ThreadSafeClass. The decrement method is not static and will synchronize on the instance used to call it. I.e., they will synchronize on different objects and thus two different threads can execute the methods at the same time. Since the ++ and -- operations are not atomic the class is not thread safe.
Also, since count is static, modifying it from decrement which is a synchronized instance method is unsafe since it can be called on different instances and modify count concurrently that way.
You have two synchronized methods, but one of them is static and the other is not. When accessing a synchronized method, based on it's type (static or non-static), a different object will be locked. For a static method, a lock will be put on the Class object, while for the non-static block, a lock will be put on the instance of the class that runs the method. Because you have two different locked objects, you can have two threads that modify the same object simultaneously.
Can anyone explain why above class is not thread safe?
increment being static, synchronization will be done on the class itself.
decrement being not static, synchronization will be done on the object instantiation, but that doesn't secure anything as count is static.
I'd like to add that to declare a thread-safe counter, I believe the simplest way is to use AtomicInteger instead of a primitive int.
Let me redirect you to the java.util.concurrent.atomic package-info.
Others' answers are pretty good explained the reason. I just add something to summarize synchronized:
public class A {
public synchronized void fun1() {}
public synchronized void fun2() {}
public void fun3() {}
public static synchronized void fun4() {}
public static void fun5() {}
}
A a1 = new A();
synchronized on fun1 and fun2 is synchronized on instance object level. synchronized on fun4 is synchronized on class object level. Which means:
When 2 threads call a1.fun1() at same time, latter call will be blocked.
When thread 1 call a1.fun1() and thread 2 call a1.fun2() at same time, latter call will be blocked.
When thread 1 call a1.fun1() and thread 2 call a1.fun3() at same time, no blocking, the 2 methods will be executed at same time.
When thread 1 call A.fun4(), if other threads call A.fun4() or A.fun5() at same time, latter calls will be blocked since synchronized on fun4 is class level.
When thread 1 call A.fun4(), thread 2 call a1.fun1() at same time, no blocking, the 2 methods will be executed at same time.
decrement is locking on a different thing to increment so they do not prevent each other from running.
Calling decrement on one instance is locking on a different thing to calling decrement on another instance, but they are affecting the same thing.
The first means that overlapping calls to increment and decrement could result in a cancel-out (correct), an increment or a decrement.
The second means that two overlapping calls to decrement on different instances could result in a double decrement (correct) or a single decrement.
Since two different methods, one is instance level and other is class level, so you need to lock on 2 different objects to make it ThreadSafe
As explained in other answers, your code is not Thread safe since static method increment() locks Class monitor and non-static method decrement() locks Object monitor.
For this code example, better solution exists without synchronzed keyword usage.
You have to use AtomicInteger to achieve Thread safety.
Thread safe using AtomicInteger:
import java.util.concurrent.atomic.AtomicInteger;
class ThreadSafeClass extends Thread {
private static AtomicInteger count = new AtomicInteger(0);
public static void increment() {
count.incrementAndGet();
}
public static void decrement() {
count.decrementAndGet();
}
public static int value() {
return count.get();
}
}
Given:
public class TestSeven extends Thread {
private static int x;
public synchronized void doThings() {
int current = x;
current++;
x = current;
}
public void run() {
doThings();
}
}
Which statement is true?
A. Compilation fails.
B. An exception is thrown at runtime.
C. Synchronizing the run() method would make the class thread-safe.
D. The data in variable "x" are protected from concurrent access problems.
E. Declaring the doThings() method as static would make the class thread-safe.
F. Wrapping the statements within doThings() in a synchronized(new Object()) { } block would make the class thread-safe.
isn't it enough to mark doThings() as synchronized in order to make that class Thread-safe ? i see that the correct answer is D but the Model answer of this question is E, But i don't understand why?
E. Declaring the doThings() method as static would make the class thread-safe.
That is kind of a tricky answer. The method is already synchronized, but on the instance, whereas the state is in a static field, i.e. on the class. Making it static synchronized is indeed the correct answer, because then it synchronizes on the class, not on a (meaningless) instance.
D. The data in variable "x" are protected from concurrent access problems.
private static int x;
This is a static variable. It is shared by all instances of the class, so synchronizing on individual instances is not helpful, in the same way as F would not be helpful, which synchronizes on a complete throw-away dummy object.
According to the language spec:
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.
This means that in the code you provided the synchronized keyword causes the method to acquire a lock on this before executing the body of the method. However, since x is static that doesn't ensure that the update to x will be atomic. (Another instance of the class could enter the synchronized region and do an update at the same time since they have different this values and thus different locks.)
However, declaring doStuff static will make all calls to the method acquire the same lock (the one on the Class) and thus would ensure mutual exclusion in the method body.
The specifications is really spelling out that:
class A {
static synchronized void doSomething() {
// ...
}
}
is literally the same thing as
class A {
static void doSomething() {
synchronized(A.class) {
// ...
}
}
}
Similarly:
class B {
synchronized void doSomething() {
// ...
}
}
is literally the same thing as
class B {
void doSomething() {
synchronized (this) {
// ...
}
}
}
By way of synchronizing the doThings() method, you are holding the lock for a particular TestSeven object. However, static variables of the class does not belong to the specific instance of the object itself. They belong to the Class object TestSeven.class. So, either you could go for a
synchronized (TestSeven.class){
int current = x;
current++;
x = current;
}
inside your doThings() method which is acquiring the Class lock inside an instance lock which is overdoing things. So, you could mark the method as static so that you end up acquiring the lock of the Class object alone.
Since x is static other threads could modify it at the same time doThings method is running. Making doThings static will stop this.
I agree with you that the correct answer is D.
I would say that E is incorrect because if I set doThings() as static and remove the synchronized keyword, I could just start up 50 TestSeven threads and it could result in incorrect x value.
Note:
I was wrong here, I missed the point that synchronized method without static actually use the instance as the lock monitor instead of the Class itself.
I have a class with a static method modifying a static variable as follows, does this method needs to be synchonized for thread safe operations ?
public final class IdManager {
private static int noOfIdsInReserveCurrently = 100;
private static final AtomicInteger allotedUserIdsCount;
public static int getNewId(){
noOfIdsInReserveCurrently--;
....
return allotedUserIdsCount.incrementAndGet();
}
}
Should this method have been synchronized?
Well it's certainly not safe as it is. Two threads could both read the value, but decrement their local copy, then both write. Badness.
You could synchronize it (and all other aspects to the variable) - but it would be better to use AtomicInteger which is designed for exactly this sort of thing. That's fine if the only shared state you're modifying is that one value; if you're trying to modify more shared state atomically (e.g. some "next ID" counter as well as the number of outstanding IDs) then you would need to either thing really, really carefully about the various interleavings, or use a synchronized block instead.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do synchronized static methods work in Java?
Can someone make me understand the fundamental difference between the following two functions:
public static void synchronized f() {… }
and
public void synchronized f() {… }
In the case of
public void synchronized f(){...}
The synchronization is per instance of the of enclosing class. This means that multiple threads can call f on different instances of the class.
For
public static void synchronized f(){...}
Only one thread at a time can call that method, regardless of the number of instances of the enclosing class.
Technically, the monitor taken by synchronized in the first example is the of the object instance and the monitor take in the second example is that of the Class object.
Note that, if you have classes of the same name in different ClassLoaders, the do not share the same monitor, but this is a detail you're unlikely to encounter.
In a "static synchnronized" method, the lock that is synchronized against is on the class itself; in a "synchornized" method, the lock is on the object. Note that this means that a "static synchronzied" method will not be blocked by a running "synchronzied" method, and vice versa. For more info, see: http://geekexplains.blogspot.com/2008/07/synchronization-of-static-and-instance.html
I think:
public void synchronized f() {… } synchronizes on object itself (this)
public static void synchronized f() {… } synchronizes on Class instance of an object (object.getClass() or SomeClass.getClass)
I can be wrong
Assuming the method f is in a class Foo. The static version will lock on the the static method call at the class level (the object returned by getClass() or Foo.class). The non static version will lock for particular instances of that class, so lets say:
Foo x = new Foo();
Foo y = new Foo();
// Locks method f of instance x, but NOT for y.
x.f();
In the static instance a call to f() will lock for both versions so only one method call to f would be executing at one time.