I have started learning synchronization in threading.
Synchronized method:
public class Counter{
private static int count = 0;
public static synchronized int getCount(){
return count;
}
public synchronized setCount(int count){
this.count = count;
}
}
Synchronized block :
public class Singleton{
private static volatile Singleton _instance;
public static Singleton getInstance(){
if(_instance == null){
synchronized(Singleton.class){
if(_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
When should I use Synchronized method and Synchronized block ? Why is Synchronized block better than synchronized method ?
It's not a matter of better, just different.
When you synchronize a method, you are effectively synchronizing to the object itself. In the case of a static method, you're synchronizing to the class of the object. So the following two pieces of code execute the same way:
public synchronized int getCount() {
// ...
}
This is just like you wrote this.
public int getCount() {
synchronized (this) {
// ...
}
}
If you want to control synchronization to a specific object, or you only want part of a method to be synchronized to the object, then specify a synchronized
block. If you use the synchronized
keyword on the method declaration, it will synchronize the whole method to the object or class.
Although not usually a concern, from a security perspective, it is better to use synchronized on a private object, rather than putting it on a method.
Putting it on the method means you are using the lock of the object itself to provide thread safety. With this kind of mechanism, it is possible for a malicious user of your code to also obtain the lock on your object, and hold it forever, effectively blocking other threads. A non-malicious user can effectively do the same thing inadvertently.
If you use the lock of a private data member, you can prevent this, since it is impossible for a malicious user to obtain the lock on your private object.
private final Object lockObject = new Object();
public void getCount() {
synchronized( lockObject ) {
...
}
}
This technique is mentioned in Bloch's Effective Java (2nd Ed), Item #70
The difference is in which lock is being acquired:
synchronized method acquires a lock on the whole object. This means no other thread can use any synchronized method in the whole object while the method is being run by one thread.
synchronized blocks acquires a lock in the object between parentheses after the synchronized keyword. Meaning no other thread can acquire a lock on the locked object until the synchronized block exits.
So if you want to lock the whole object, use a synchronized method. If you want to keep other parts of the object accessible to other threads, use synchronized block.
If you choose the locked object carefully, synchronized blocks will lead to less contention, because the whole object/class is not blocked.
This applies similarly to static methods: a synchronized static method will acquire a lock in the whole class object, while a synchronized block inside a static method will acquire a lock in the object between parentheses.
Define 'better'. A synchronized block is only better because it allows you to:
- Synchronize on a different object
- Limit the scope of synchronization
Now your specific example is an example of the double-checked locking pattern which is suspect (in older Java versions it was broken, and it is easy to do it wrong).
If your initialization is cheap, it might be better to initialize immediately with a final field, and not on the first request, it would also remove the need for synchronization.
Difference between synchronized block and synchronized method are following:
- synchronized block reduce scope of lock, but synchronized method's scope of lock is whole method.
- synchronized block has better performance as only the critical section is locked but synchronized method has poor performance than block.
- synchronized block provide granular control over lock but synchronized method lock either on current object represented by this or class level lock.
- synchronized block can throw NullPointerException but synchronized method doesn't throw.
synchronized block:
synchronized(this){}
synchronized method:
public synchronized void fun(){}
synchronized should only be used when you want your class to be Thread safe. In fact most of the classes should not use synchronized anyways. synchronized method would only provide a lock on this object and only for the duration of its execution. if you really wanna to make your classes thread safe, you should consider making your variables volatile or synchronize the access.
one of the issues of using synchronized method is that all of the members of the class would use the same lock which will make your program slower. In your case synchronized method and block would execute no different. what I'd would recommend is to use a dedicated lock and use a synchronized block something like this.
public class AClass {
private int x;
private final Object lock = new Object(); //it must be final!
public void setX() {
synchronized(lock) {
x++;
}
}
}
In your case both are equivalent!
Synchronizing a static method is equivalent to a synchronized block on corresponding Class object.
In fact when you declare a synchronized static method lock is obtained on the monitor corresponding to the Class object.
public static synchronized int getCount() {
// ...
}
is same as
public int getCount() {
synchronized (ClassName.class) {
// ...
}
}
Because lock is expensive, when you are using synchronized block you lock only if _instance == null
, and after _instance
finally initialized you'll never lock. But when you synchronize on method you lock unconditionally, even after the _instance
is initialized. This is the idea behind double-checked locking optimization pattern http://en.wikipedia.org/wiki/Double-checked_locking.
It should not be considered as a question of best for usage, but it really depends on the use case or the scenario.
Synchronized Methods
An entire method can be marked as synchronized resulting an implicit lock on the this reference (instance methods) or class (static methods). This is very convenient mechanism to achieve synchronization.
Steps A thread access the synchronized method. It implicitly acquires the lock and execute the code. If other thread want to access the above method, it has to wait. The thread can't get the lock, will be blocked and has to wait till the lock is released.
Synchronized Blocks
To acquire a lock on an object for a specific set of code block, synchronized blocks are the best fit. As a block is sufficient, using a synchronized method will be a waste.
More specifically with Synchronized Block , it is possible to define the object reference on which are want to acquire a lock.
来源:https://stackoverflow.com/questions/20906548/why-is-synchronized-block-better-than-synchronized-method