I have a confusion about object lock.
The below class having 4 methods, the method addB() is synchronized.
In my scienario, there are 4 threads. When a thread-2 access the addB() method (it creates a lock on Test object), will there any other thread access addC() or addD() same time?
Does the Object lock allows only one thread at a time ?
class Test{
private Integer a;
private Integer b;
private Integer c;
private Integer d;
public void addA(){
synchronized(a) {
a++;
}
}
public synchronized void addB(){
b++;
}
public void addC(){
c++;
}
public void addD(){
d++;
}
}
EDIT:
I have 3 threads(t1, t2 and t3) , and each one is going to access addB(), addC() and addD(). If thread t1 access the method addB(), could thread t2 access addC() method simultaneously? If not what would be t2 state?
class Test{
private Integer a;
private Integer b;
private Integer c;
private Integer d;
public void addA(){
synchronized(a) {
a++;
}
}
public synchronized void addB(){
b++;
}
public synchronized void addC(){
c++;
}
public synchronized void addD(){
d++;
}
}
A lock does indeed allow only one thread at a time, but different locks do not affect each other.
In your example, you have two locks - one on the mutex belonging to a, and one on the mutex belonging to this (which is implicit when you use the synchronized keyword, as you correctly mentioned in your post).
So calls to addB() will be synchronized but will not block calls to any other method. If one thread holds the lock on this, another thread can hold the lock on a, and multiple other threads can execute addC() and addD() concurrently.
Edit: as an aside, you might be interested to learn about the AtomicInteger class if you really are working with Integers. They provide atomic operations such that you don't need to worry about synchronizing around them.
A synchronized block is just an environment where you treat the object it was "executed" on as a reentrant lock. Indeed, only one thread is allowed locking on an object at the same time.
The methods C and D never lock and can be executed any time by any thread.
And as other pointed, when you execute a++, you create a new instance of Integer.
You have two locks in your code, only one Thread will be able to traverse either Lock #1 or Lock #2. Both locks are independent, meaning they do not exclude Threads from each other.
Lock #1 synchronizes on the a Object
public void addA(){
synchronized(a) {
a++;
}
}
lock #2 Synchronizes on the Test Instance (this)
public synchronized void addB(){
b++;
}
addC() and addD() have no locks on them at all, any amount of Threads can access these concurrently.
Lock provides a mechanism for synchronizing the thread. this means that at the same point in time only one thread can access the AddB method of your object.
Unless you release the lock after completion of the code, the next code iteration cannot enter the block.
Locking of thread depends on the instance of the object used
e.g:
class MyClass extends Thread{
Test instanceObj=null;
public MyClass(Test obj){
instanceObj=obj;
}
public void run(){
obj.addB();
}
}
the addB() function can be rewriten as
public void addB(){
synchronized(this){
//func
}
}
Here the lock is on the object for access the snippet of the function.
other functions can be accessed by other threads.
More over the lock on addA is on an object obj.a which has its own indepedent lock.Hence two different threads can acccess addA and addB at the same time.
Related
class MutableInteger {
private int value;
public synchronized void increment() {
value++;
}
public synchronized int getValue() {
return value;
}
public void nonSync(){
}
}
I am trying to understand how the synchronization keyword works.
I have a class with methods that are sychronized, this means that on that specific instance of the object, only one thread can call that method at a time? This only pertains to that method though? So if a thread A was calling incriment, thread B would have to wait until thread A was done executing the method? But this is only a method by method basis?
however, if I did
synchronized(this) {
//code
}
that would lock the entire instance of the object?
Does that make sense.. I get in essence what this is supposed to be doing, just trying to fill the gaps
You are right, synchronized methods are locking the instance itself.
So writing the followings:
synchronized myMethod() {
//code
}
Is essentially the same behavior as if you have written:
myMethod() {
synchronized(this) {
//code
}
}
Note, that this is simply an Object and is used as the lock as any other object would be used - the lock can be owned by only one thread at a time, the others must wait for it to enter a synchronized block using the same object. Since methods having the synchronized keyword behave such a way, they share the lock being the instance itself.
So, if you have an increment() and decrement() method both marked synchronized, then only either of the two can be used and by one thread at a time.
Meanwhile, other methods without the synchronized keyword remain completely unaffected and will function the same, whether there are synchronized methods around them or not.
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 have a small confusion. Please have a look at the code below.
public class ThreadDemo {
//non-static synchronized method
synchronized void a(){
actBusy();
}
//static synchronized method
static synchronized void b(){
actBusy();
}
//static method
static void actBusy(){
try{
Thread.sleep(1000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
final ThreadDemo x = new ThreadDemo();
final ThreadDemo y = new ThreadDemo();
Runnable runnable = new Runnable() {
public void run() {
int option = (int) (Math.random() * 4);
switch (option){
case 0: x.a();
break;
case 1: x.b();
break;
case 2: y.b();
break;
case 3: y.b();
break;
}
}
} ;
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
t1.start();
t2.start();
}
}
I know for sure that invocation of this sequence is possible.
x.a() //in Thread-1
y.b() //in Thread-2
Though still I have a small confusion that, we can easily see x.a() also calls actBusy() method
which is a
static method. Method b() is a static synchronized method calling a non-synchronized
static method. When thread-2 gets a class level lock, the why call of actBusy() from Thread-1
is not blocked?
I am just logically confused, if a thread gets a class level lock, that class other
non-synchronized static methods remain open to be called from other methods (instance method). Why?
then why call of actBusy() from Thread-1 is not blocked?
Since your actBusy method is NOT synchronized. Even if you acquired class level lock you can invoke non-synchronzied static methods.
The point of marking the methods as synchronized is to enable locks. Only methods declared as synchronized are subjects to these locks. So if you acquired a lock (suppose class level lock) then any non-synchronized method acts as before and isn't aware of lock being acquired. This allows you to decide which methods need to be blocked and which don't.
static synchronized method has a lock on the class object, while non static synchronized method has a lock on the instance object (this) - so both methods can be invoked concurrently, and one thread will run 1 while the other run the 2nd.
However, note that there is no race condition available in your code, because race condition requires a write, and such does not exist in these methods.
actBusy() is itself not synchronized but the callers methods are.
So Thread 1 does not block as it acquires lock on this object and no other thread holds lock on this, so it is able to call it without any problem.
That is because the non-static synchronized method locks on this the present instance and not on class object.
x.a() grabs a lock on the present instance i.e x and no other thread will be able to enter method a() of x until the present the present thread releases the lock.
Thread 1 --> x.a() //acquires lock and holds it
Thread 2 ---> x.a() //blocks here until Thread 1 releases lock on x
EDIT:
Class Object != Instance
So according to JMM they are different objects and two threads don't interfere with each other. So it allows you to call it.
EDIT 2:
why does it allow calls to other static methods? Any logic behind it?
Suppose this:
public static synchronized int statefulMethod(){
//this should be protected
}
public static int nonStatefulMethod(){
//Just returns a static value such as 5
//so this is thread safe as it does not have any state
}
public static synchronized int otherStatefulMethod(){
//this should also be thread safe
}
So if thread 1 is in method statefulMethod() which is having some shared state to protect so it uses class level lock. Now thread 2 calls nonStatefulMethod() then it should not logically block as that method is thread safe and there is no point in making that thread block here.
Now if thread 3 calls the otherStatefulMethod() while thread 1 is holding class lock then thread 3 will have to wait as that method is also static-synchornized.
Lock objects are not hierarchical. Therefore obtaining a lock on the class itself does not supersede locks on instances of your class. They are separate lock objects and will only block code that attempts to lock on exactly that same object.
So if a thread enters a static synchronized method, the only threads that will be blocked are those also trying to enter a static synchronized method on the same class. Threads that are merely trying to enter an non-static synchronized method are unaffected - they are only competing against threads trying to enter non-static synchronized methods on that same object instance.
Regarding your comment below - only static methods marked synchronized are subject to the class level lock. If you want other static methods to be blocked, you must also mark them synchronized.
Why is this the case? Well, it would be rather presumptuous for the compiler to assume you need to lock all your static methods simply because one is marked as synchronized. It is assumed that the programmer knows which methods must be synchronized in order to ensure thread safety.
I am not clear the concept of
Java Thread acquires an object level lock when it enters into an instance synchronized java method and acquires a class level lock when it enters into static synchronized java method.
What does it mean When it says object level lock and class level lock ?
For example:
public class Counter{
private static int count = 0;
private int count2 = 0;
public static synchronized int getCount(){
return count;
}
public synchronized setCount(int count2){
this.count2 = count2;
}
}
getCount() here will lock Counter.class object while setCount() will lock on current object(this). What does that this refer to ? Does that mean when getCount() get called another thread can't access setCount() since the whole class is locked ?
What does it mean When it says object level lock and class level lock ?
When you lock on a static method you are locking on the Class object itself and there is one of these per ClassLoader. In your example,
public static synchronized int getCount(){
This is locking on the Counter.class object and is the same as:
public static int getCount() {
synchronized (Counter.class) {
}
If you are instead locking on a method that is not static then you are locking on the instance of the object that owns that method. In your example:
public synchronized void setCount(int count){
This is the same as locking on the particular Counter instance and is equivalent to:
public void setCount(int count){
synchronized (this) {
...
So if you have 2 Counter objects, counter1 and counter2, and 1 thread is calling counter1.getCount() and the other is calling counter2.getCount() at the same time, then they will both lock on the same Class object and one will block the other.
But if the 2 threads are instead calling counter1.setCount(...) and counter2.setCount() they will be locking on different objects -- counter1 and counter2 respectively. They will not block each other.
As mentioned, it is very bad form to have asymmetry on your setters and getters and it is unusual to have either be static.
Does that mean when getCount() get called another thread can't access setCount() since the whole class is locked ?
No. If getCount() is called, the Counter.class is locked and when setCount(...) is called counter1 or counter2 is locked. The only time a lock blocks a thread is when the same object has been locked by another thread. Just because there is a lock on Counter.class does not mean that there is some sort of uber-class lock. The only time that will block another thread is if it too locks on Counter.class.
I'd take a moment to read Sun's great documentation on how synchronized works.
In Java, each class and each instance of a class are endowed with their intrinsic locks. These are the locks acquired and release on entry to and exit from synchronized methods.
As usual this refers to the instance on which setCount() was called and because each instance has its own intrinsic lock the second call to setCount() will not block as long as it is invoked on another instance of your class, but an attempt to call setCount() on an instance on which another setCount() call is in progress will block.
Class lock and instance locks are different and thus getCount() and setCount() never get in each others way.
static members are associated to the class not to a particular instance. As a result a synchronization on a static member effectively synchronizes over the whole class as static is a class member
instance members are associated with instances of the class (e.g. the intrisic this lock) so if you synchronize on a member field (non-static) or on this then you have a lock associated with an instance object.
In your example getCount synchronizes on the intrinsik lock of the class. Effectively you are doing:
public setCount(int count){
synchronized(this){
this.count = count;
}
}
You would be synchronizing in a class level if you did:
static Object count = new Object();
synchronized(count){
}
Each object in Java has a mutex. Since a class is represented by an object of type java.lang.Class, each class has a mutex too. synchronized instance methods lock the instance's mutex, while synchronized static methods lock the mutex for the corresponding java.lang.Class instance.
class C {
synchronized T myMethod() { ... }
static synchronized T myStaticMethod() { ... }
}
is equivalent to
class C {
T myMethod() {
synchronized (this) { ... } // An object level lock.
}
static T myStaticMethod() {
synchronized (C.class) { ... } // A class level lock
// is really just an object level lock an a Class.
}
}
Once you know what object you're synchronizing on, you can understand the synchronized keyword by breaking it down.
synchronized (x) {
body();
}
performs like
monitorenter(x); // locks x or throws NullPointerException if x is null.
try {
body();
} finally {
monitorexit(x); // unlocks x
}
where monitorenter and monitorexit are Java bytecode instructions that respectively block until they acquire the mutex, and release the mutex.
Since synchronized introduces a "protected region", like try ... finally, the lock will be released even if an exception is thrown, though killing the thread will leave the lock unreleased possibly leading to deadlock.
consider the following code:
public class SynchronizedCounter extends Thread {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public void run() {
for(;;)
increment();
}
}
static void main(String[] args) {
SynchronizedCounter counter = new SynchronizedCounter();
counter.start();
for(;;)
counter.decrement();
}
does this means that increment() and decrement() methods will wait for each other to finish or not?
EDIT:
and this does not wait?
static void main(String[] args) {
SynchronizedCounter counter1 = new SynchronizedCounter();
SynchronizedCounter counter2 = new SynchronizedCounter();
counter1.start();
for(;;)
counter2.decrement();
}
Yes, the synchronized keyword is a shorthand for:
synchronized(this) {
//...
}
So both methods are effectively locking on the same mutex object. If you want them to be independent from each other (which is a bad idea in this example as they both access the same value), see Object locking private class members - best practice? (Java).
BTW your SynchronizedCounter should implement Runnable rather than extending a Thread since you are passing it to other thread's constructor - now it is a bit confusing.
The lock is always on the entire object. If any of it's the synchronized members are accessed.
In your first example, there are two threads contending for the same counter object, the one you started explicitly (which calls the increment() method in infinite loop) and the other thread is the main thread (which calls the decrement() infinitely).
In the second example, there are two objects created counter1 and counter2. These will have their own locks independent of each other. Locking of one object does not affect the other threads from accessing other object. The two threads (the explicit and the main thread) acquire lock on two different objects and hence there in no contention.
does this means that increment() and decrement() methods will wait for each other to finish or not?
NO, it means that no other thread will be able to call increment() and decrement() when one thread is within them. To be complete, other thread could not execute any synchronized method of this instance/object
You could call any other synchronized method from a synchronized one without lock on the same instance/object