Reputation: 1451
I am learning synchronized blocks with locks.I want to know the difference between this lock and some third party lock that provided in the program.
public class NewThread extends Thread {
StringBuffer sb;
NewThread(StringBuffer sb){
this.sb=sb;
}
public void run(){
synchronized(this.sb){
for(int i=0;i<1000;i++){
System.out.print(sb);
try{
Thread.sleep(5*60);
}
catch(Exception e){}
}
char c = this.sb.charAt(0);
this.sb.setCharAt(0, ++c);
}
}
public static void main(String[] args){
StringBuffer sb=new StringBuffer("A");
NewThread nt=new NewThread(sb);
NewThread nt1=new NewThread(sb);
NewThread nt2=new NewThread(sb);
nt.start();
nt1.start();
nt2.start();
}
}
If i am going to put
public void run(){
synchronized(this){
for(int i=0;i<1000;i++){
System.out.print(sb);
try{
Thread.sleep(5*60);
}
catch(Exception e){}
}
char c = this.sb.charAt(0);
this.sb.setCharAt(0, ++c);
}
}
here in the above run method i gave this in the synchronized block ...i want the difference between them
i am having one more question ,if we are giving a lock object in synchronized block and we are not using that object inside that block then does we observe any thing specific compared to normal block
Upvotes: 0
Views: 6690
Reputation: 26882
Others have already answered but to add my 2 cents,
a) First example is ok, in the sense that the synchronized
keyword is guarding the StringBuffer
Threads are sharing one lock.
b) Second example is not ok. You are giving each thread a different lock. In effect, it doesn't have any effect (in fact, modern Java compilers remove such locks completely). Locks are meaningful if more than one thread uses it.
You could think of it like this:
If you share a bathroom, you better have one lock for the bathroom (like its door key). If you'd ask everybody to lock their own, individual iPhone before using the bathroom, it would be surely useless. Note that the shared look does not need to be the door key. You might as well as pick one iPhone and use it as the bathroom "key" (everybody has to lock that iPhone before using the bathroom, and only the guy who locked it may unlock it). In real-life that sounds absurd, but that's pretty much what we do with mutexes.
c) The second example can be considered buggy, but in practice, you won't see the effect of the race condition. This is because StringBuffer
synchronizes internally. If you use StringBuilder
instead, you might be able to see race conditions (depends on runtime conditions).
Upvotes: 3
Reputation: 13356
If you have concurrent development experience with general OS API, e.g. pthread library in Linux, you may have a knowledge that we should use lock or other data structure to synchronize processes/threads accessing critical section(where shared object may be modified).
Java use lock to implement synchronization block. Synchronization block is a kind of mechanism(called monitor in operating system) encapsulating tedious operation related to lock. Each object has a lock in java. When synchronized, lock in shared object is locked at first(also we can say other process require lock of the shared object). If some thread fail to acquire the lock, that means some other thread is now holding the lock, it must wait until other thread release the lock and re-acquire again until it hold the lock and then enter the critical section.
The first code snippet use lock in instance of StringBuffer, i.e. sb, each thread will try to get sb's lock(invoke lock_of_sb.lock() before running the code. Only that acquired sb's lock successfully can eventually execute the code.
As to the second code, which is equivalent to
public synchronized void run(){
for(int i=0;i<1000;i++){
System.out.print(sb);
try{
Thread.sleep(5*60);
}
catch(Exception e){}
}
char c = this.sb.charAt(0);
this.sb.setCharAt(0, ++c);
}
I don't think it behaves as you expected. It acquire lock in this object, however, this object is never shared. So the shared sb is exposed into the critical section without any synchronization.
The link will give you another working way to achieve synchronization.How to synchronize static method in java Although the question itself is about static method, it also works well to instance member method.
Upvotes: 4
Reputation: 2917
In Java each object can be used as Mutex (See Mutual Exclusion). This means that only one thing can synchronize on an object at any time, which object you use is generally irreverent although it should be as specific as possible. For example if multiple threads are accessing a List, you should synchronized on that list rather than on the entire object (this) so that other things that need something else in the object may access it.
I think the article on mutual exclusion may help to clarify the matter. In essence, only one thread may get the key to a "lock" -- that lock is what is inside synchronized. So long as everything accessing your resource requests the lock on the SAME object, you are protected.
Upvotes: 2