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.
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.
package indi.JavaLearn;
public class MultiThread {
private static int shared;
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
(new Thread() {
public void run() {
write2();
}
}).start();
}
}
public synchronized static void write2() {
int i = 0;
while (i < 2) {
shared++;
System.out.println("write," + Thread.currentThread().getId() + "," + String.valueOf(shared));
i++;
}
}
}
Result
write,12,1
write,12,2
write,15,3
write,15,4
write,16,5
write,16,6
write,14,7
write,14,8
write,13,9
write,13,10
The synchronized modifier in write2 allows the method to only be run by one thread at a time - you need to remove it for it to be run on multiple threads at the same time.
If what you actually want to do is lock the shared variable, use a synchronized block:
synchronized(shared){
shared++;
System.out.println("write," + Thread.currentThread().getId() + "," + String.valueOf(shared));
}
public synchronized static void write2() is a static synchronized method implies lock/monitor is maintained at Class level instead of Object level.
static synchronized methods are synchronized on the Class object. If one thread is executing a static synchronized method, all other threads trying to execute any static synchronized methods will be blocked unless the lock is released by locked thread.
Non-static synchronized methods synchronize on this(means Object, which is an instance of the class). If one thread is executing a synchronized method, all other threads trying to execute any synchronized methods on that Object (but not the class) will be blocked.
Have a look at related SE questions:
Static versus non-static lock object in synchronized block
What is the difference between synchronized and static synchronized?
You can find good documentation about the concepts at this link
You might wonder what happens when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
You should read about concurrency in Java, specifically what the synchronized keyword means.
Now, on to what is going on with your code ...
When one thread (ex. the thread with the id 12) calls the write2() method it obtains a lock (mutex) on the object. Then it performs the code within the method body (i.e. the loop and print statement). Finally, it releases the lock on the object to allow another thread that is waiting to perform the method. Therefore, you always see the print statements occurring in segments of two.
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.
All of you know the synchronization context in Java that they are can be
on the instance.
on the java.lang.Class instance for a certain loaded class.
on a given object
And I need to ask; When i write
Dimension d = new Dimension();
synchronized(d){
// critical atomic operation
}
synchronization of a given object equal to synchronization on the instance practically.
so when I write synchronized(d) where d is an instance of object, then the thread will gain the lock for all synchronized instance block of code.
Can you please give me more details about synchronization context.
Your replies will be appreciated.
The synchronized keyword provides serial access to the block of code (which could be an entire method) it introduces. Serialization of access is done by using an object as a mutex lock.
The three basic uses of synchronized are:
A. On a static method:
static synchronized void someStaticMethod() {
// The Class object - ie "MyClass.class" - is the lock object for this block of code, which is the whole method
}
B. On an instance method:
synchronized void someInstanceMethod() {
// The instance - ie "this" - is lock object for this block of code, which is the whole method
}
C. On an arbitrary block of code:
private Object lock = new Object();
void someMethod() {
synchronized (lock) {
// The specified object is the lock object for this block of code
}
}
In all cases, only one thread at a time may enter the synchronized block.
In all cases, if the same lock object is used for multiple blocks, only one thread may enter any of the synchronised blocks. For example, if there are two - other simultaneous threads calling the methods will block until the first thread exits the method.
Applying the synchronized keyword to a non-static method is shorthand for:
public void method() {
synchronized(this) {
// method
}
}
If you apply synchronized to a static method, then it locks the class object (MyClass.class) whilst the method is called.
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.