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.
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 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
I need some clarificaton on how the syncronized keyword works in java 6.
Using the following example class.
class Carrier {
private String[] _collection = new String[2];
public Carrier() {
this._collection[0] = "abc";
this._collection[1] = "123";
}
public syncronized void change(int cId) {
Thread.sleep(3000);
this._collection[cId] = "changed";
}
}
Now, some place in the application, referencing the same object instance of the Carrier class, the .change() method is called, possibly at the same time.
...carrier.change(1);
...
...carrier.change(1);
Will the syncronized keyword prevent asyncronized execution of the method? Will it simply queue the call to .change(), waiting for each one to complete?
Yes, the second thread will block while the first thread is executing. That's because they both try to acquire the monitor on the same object - via this, in this case. So your change method is equivalent to:
public void change(int cId) {
synchronized (this) {
Thread.sleep(3000);
this._collection[cId] = "changed";
}
}
Personally I don't like synchronizing on "this" as it means any other code with access to the object itself could acquire the same monitor. I prefer to create an object just for locking which only code within the class has access to:
private final Object lock = new Object();
public void change(int cId) {
synchronized (lock) {
Thread.sleep(3000);
this._collection[cId] = "changed";
}
}
That will still have the same effect in terms of two threads calling change on the same object, because both threads will still be acquiring the same monitor - just the one associated with the lock-specific object.
Yes, it will prevent the two method calls from executing at the same time.
That is really what the main use of the synchronized keyword is.
When one synchronized method runs, it obtains a 'lock' on the object it is called on. That means no other synchronized code can be run on that object while that method holds the lock. Once the method is done executing, it will release the lock, and other synchronized methods can obtain a lock on that object.
Yes, and yes. (Note that it's synchronized, not syncronized)
Yes - the synchronized keyword prevents simultaneous execution of the method by different threads.
Note: A "class method" is a static method. An "instance method" (ie non-static) is what you have in your question.
synchronized are used for preventing simultaneously accesses in cuncurrent programming.
For example when you have to client, one that reads and another that writes:
Lock here for an exhaustive explanation.