I'm not used to working with synchronized. Does the following snippet look right?
public void setNewSessionListener(NewSessionListener newSessionListener) {
if (this.newSessionListener != null)
synchronized (this.newSessionListener) {
this.newSessionListener = newSessionListener;
}
else
this.newSessionListener = newSessionListener;
}
More specifically do I need to perform a null check? I have a gut feeling there is something fundamentally wrong with that code.
There are two mistakes. The first one is that if you access a field which requires synchronization, you always have to access it with the same lock held. Also you have to check if the field is null and write to the field in the same sychronized block, because otherwise when you write something to the field, it may already be not null.
The second one is that it is best to sychronize on something that doesn't change, in other words, on a static final field or on the instance itself. For example, you can create a lock object specifically for this purpose:
private static final Object LOCK = new Object();
And then you will write:
synchronized (LOCK) {
if (this.newSessionListener == null) this.newSessionListener = newSessionListener;
}
Your feeling is right. You should do the null check inside the synchronized block. Otherwise the block won't prevent double initialization. Furthermore, you shouldn't synchronize on this.newSessionListener which you are about to change - choose an object (reference) which is going to stay around for the whole scope of the block. This is the only way to guarantee that only one thread can enter this block of code at any point in time. The typical way to achieve this is to synchronize on this. Alternatively, you may synchronize on a private final object, kept for this sole purpose.
Moreover, ultimately you are performing the same assignment in both the if and the else branches, which is probably not what you want.
This is, at a minimum, a very bad idea. You are synchronizing on an object you then assign to.
Because you are using synchronized I assume this is called asynchronously and it could be called by one thread while another thread is inside this code. If so, you are not locking on a common object, you are locking on the value it is holding at that point in time.
Probably, and I stress probably, you can do synchronized (this). That will insure that all calls to this method for this specific object are synchronized. And that calls to other instances of this class are locked for that other object - but not across instances.
If you want to synchronize across all instantiated objects, call synchronized (YourClass)
Here's another possibility (i tend to prefer explicit locks over the synchronized block):
private ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// do your synchronized code here.
}
finally {
lock.unlock();
}
Though just by looking at your code, i'm not sure why there's even an if block. Why are you synchronized in one case, and not the other? Especially considering you're making the same assignment in either case?
Related
I have just encountered code where synchronization was done on wrong class:
public class Test
{
public static volatile Test instance = null;
public static void setIfNull(Test newInstance)
{
synchronized (WRONG.class) // should be synchronized (Test.class)
{
if (newInstance == null)
throw new IllegalArgumentException("newInstance must not be null.");
if (instance == null) instance = newInstance;
}
}
}
Above error would not happen if whole method was synchronized:
public class Test
{
public static volatile Test instance = null;
public static synchronized void setIfNull(Test newInstance)
{
if (newInstance == null)
throw new IllegalArgumentException("newInstance must not be null.");
if (instance == null) instance = newInstance;
}
}
The way I see it, second piece of code is more error proof than first one.
Are there any pitfalls of using method synchronization over synchronization block concerning above code pattern?
Warning: In above code instance field is not properly encapsulated. Being public member nothing prevents external code not only to read it, but also write to it in thread unsafe manner. This code should not be used as proper thread safe singleton example because that is not what it is.
Are there any pitfalls of using method synchronization over synchronization block concerning above code pattern?
Since this:
public static synchronized void setIfNull(Test newInstance) {
...
}
...is exactly the same (JLS 8.4.3.6) as this:
public static void setIfNull(Test newInstance) {
synchronized (Test.class) {
...
}
}
...what you are really asking is: "What is the difference between synchronizing on some other class object WRONG.class and on This.class?".
The only thing to look out for is whether something else in your code decides to synchronize on Test.class.
1) One significant difference between synchronized method and block is that, Synchronized block generally reduce scope of lock. As scope of lock is inversely proportional to performance, its always better to lock only critical section of code. One of the best example of using synchronized block is double checked locking in Singleton pattern where instead of locking whole getInstance() method we only lock critical section of code which is used to create Singleton instance. This improves performance drastically because locking is only required one or two times.
2) Synchronized block provide granular control over lock, as you can use arbitrary any lock to provide mutual exclusion to critical section code. On the other hand synchronized method always lock either on current object represented by this keyword or class level lock, if its static synchronized method.
3) Synchronized block can throw throw java.lang.NullPointerException if expression provided to block as parameter evaluates to null, which is not the case with synchronized methods.
4) In case of synchronized method, lock is acquired by thread when it enter method and released when it leaves method, either normally or by throwing Exception. On the other hand in case of synchronized block, thread acquires lock when they enter synchronized block and release when they leave synchronized block.
Read more: http://java67.blogspot.com/2013/01/difference-between-synchronized-block-vs-method-java-example.html#ixzz3qAc5gOJy
I cant remember any pitfalls when you synchronize whole methods. Of course those are more "expensive" that just locks around certain areas.
If you're not sure i would always go for the synchronized method first until you encounter is as a bottleneck.
To avoid blocking on the wrong object simple create an instance variable:
private final Object block = new Object();
And use this when you need sychronization. Anyway when you do so, keep in mind that other methods called by different threads dont respect this and you get side effects. So you have to be careful when going this way.
I read quite some books on those topics thats an really concrete answer ist hard to mark as the correct one.
I recommend that you read "Java Concurrency in Practice" from Brian Goetz.
Also "Java Core" from Angelika Langer, Klaus Kreft (a book that goes into deep when it comes to using the volatile keyword) (German Book, still curious that no one translated this into english as it is a masterpiece in its area).
Also you could use reentant locks to get fair locking if you like.
One of my textbook mentions that the argument of synchronized() must be this... I know it is wrong. But I heard that since synchronized(this) is safer, one should always use it. Is that true ?
Thank you:)
No it does not have to be always this. Also it simply cannot be in the case of static methods, because there is no this.
Also it is sometimes considered wrong to synchronize to this, because then lock object is visible outside.
public class Example {
private final Object lock = new Object();
// does not compile, there is no 'this' in static context.
public static void staticMethod() {
synchronized (this) {
}
}
public void method() {
int x = 3;
//there is risk that someone else outside our code
//uses same lock
synchronized (this) {
}
//this lock is private
synchronized (lock) {
}
}
}
One of my textbook mentions that the argument of synchronized() must be this... I know it is wrong.
That is incorrect. Either the textbook is incorrect, or you have misunderstood it. The Java language allows you to synchronize on any (non-null) object reference.
But I heard that since synchronized(this) is safer, one should always use it. Is that true?
No that is not true either. It is not safer, and you certainly shouldn't always lock on this.
In fact if you are writing a general purpose library class that needs to lock "itself", it is often a good idea to declare a private lock field; e.g.
private final Object myLock = new Object();
... and lock that object rather than this. This eliminates the kind of problems that can occur is some external code decides to lock the library object for some reason, leading to unwanted contention, and possibly deadlocks between the library classes methods and the external code.
I suspect that the point that the textbook was trying to make is that all methods that are using primitive locks to give mutual exclusion and synchronization on a data structure must use the right object as the lock. This isn't necessarily the data structure object itself, but it does need to signify that object ... in some sense. (If you don't lock the object that signifies the data structure, you risk having one thread not excluding others while it uses / updates the data structure.)
Here is a sketch of the problem that private locks aim to avoid.
/** This class implements thread-safe getting / setting by synchronizing on 'this' */
public class IntHolder {
private int value;
public int getValue() {
synchronized(this) { return value; }
}
public void setValue(int value)
synchronized(this) { this.value = value; }
}
/* Somewhere else, some other code (the "external code") used a holder instance
as the lock for some larger-scale synchronization. */
IntHolder h = ...
synchronized (h) {
/* Do something that takes a long time ... */
}
The problem is that while the external code holds that lock on h, other threads won't be able to read or change the holder's value. If that was intended ... that is fine. However, if the thread-safety of the IntHolder type is intended to be "just an implementation detail" you now a potentially unexpected failure case.
IMO you're better off using 'volatile' and 'synchronized' on fields and methods if you're unsure whether synchronized(this) is a good idea in that particular place.
to put it simply, volatile places an intrinsic mutex on a variable; synchronized places an intrinsic mutex on a function call; synchronized block places an intrinsic mutex around that piece of code locked by the parameter.
Usually you'd make a lock and lock on a Object, but sometimes you want to lock on the instance itself... though, I'd advise caution on locking with a whole class instance if you only need access to one of it's members/fields (something you could've solved using synchronized and volatile in the first place)
The real reason why you might want (or not want) to lock on this is scope of the lock, you can see the lock if you lock on this. if you init a private object, the lock is hidden away.
The argument of synchronized is simply which object the hold will be placed on. It depends on what you want to do in the synchronized block that will determine what the argument should be. Using this puts a hold on the current object.
As a personal anecdote, in the project I'm currently working on, all of my synchronized holds are on COM ports, so that there's no collisions between sending and receiving packets
it doesn't matter which lock you use. Every java.lang.Object can act as a lock. You have to make sure that all operations that work on the same mutable state use the same lock.
so synchronized(this) is exactly as safe as
private final Object lock = new Object();
synchronized(lock)
If you declare a non-static method as synchronized:
public synchronized void doSomething()
{
...
}
then it is synchronized on this. So if your goal is for a synchronized block to be synchronized with synchronized non-static methods like the above, then you do need to use synchronized(this).
But you are correct: you can also write synchronized(someOtherObject), as long as you're aware that that will lock out synchronized methods of someOtherObject rather than of this.
(For static methods, by the way, synchronized synchronizes on the Class instance representing the containing class.)
No , this is not necessary that you should use this .Even you an apply lock on any other object which not an instance of this.
synchronized(obj1){
-------
}
synchronized(obj2){
-------
}
In a single method you can write something like above where you first acquire the lock on some object obj1 and then did work and released and then acquire the lock on obj2.
Aaah, the infamous Avoid synchronized(this) in Java?.
There is, actually, no difference between
public synchronized void doThis() {
}
and
public void doThis() {
synchronized (this) {
}
}
Except on the bytecode level. Both address thread-safety. They both pose a problem as you can potentially introduce deadlock, if (for example, you set a lock of the same class, within its synchronized block).
If you're worried about deadlock, then a dedicated lock should be used, like so:
public class MyClass {
private final Object lock = new Object(); //Must be final
public void doThis() {
synchronized (lock) {
}
}
}
Alternatively, use the Java java.util.concurrent.Lock interface and the java.util.concurrent.locks.ReentrantLock implementation to do basically lock..
I ran into some (production!) code that looks like the snippet below:
synchronized(some_object) {
some_object = new some_object()
}
I would expect this to be subject to all sorts of horrible race conditions, and that a second thread Could possibly enter this block one the new object is created. My Java chops aren't good enough to state definitively the expected behavior of above, so curious what you folks have to say before I refactor this.
This could actually be OK depending on what is going on. You would need to understand the larger context. The synchronization will be on the object that's pointed to by some_object at the beginning of the block. There is not enough information from your description to see that it's a bug.
The synchronization itself will work just fine.
As Francis says, this may not be a problem. Your snippet is equivalent to this:
SomeObject saved = some_object;
synchronized(saved) {
some_object = new SomeObject()
}
The synchronization is on the object that was referenced when entering the synchronized block. Pointing the reference to another object inside the synchronized block does not effect the synchronization at all. It is still synchronized over the "old" object.
This is pretty bad. synchronized is best used on final class members.
The modern approach to creating an object in a thread safe manner is using AtomicReference compareAndSet in a loop as discussed in Goetz's Java Concurrency in Action (chap 15). This does not block your threads and offers far greater performance than a synchronized block.
private final AtomicReference<SomeObject> someObject = new AtomicReference<>();
void buildIt() {
SomeObject obj = new SomeObject();
SomeObject current = someObject.get(); //probably null, but doesn't matter
while (true) {
if (someObject.compareAndSet(current, obj))
break;
}
}
What is the difference or impact between using the synchronized block as in method1 and method2?
class A
{
private Object lock = new Object();
...
...
private void method1()
{
synchronized(A.class)
{
.....
}
}
private void method2()
{
synchronized(lock)
{
....
}
}
}
In first method all threads that use ANY instance of the class A will be syncronised.
In second method all threads that use THIS instance of the class A will be syncronised.
Since A.class is avaliable to others, it is public in effect. If something else uses it to synchronize access to some section of code then your section of code could be blocked. This might be good or bad; but you don't have control over it.
Using an internal object allows you to decare it as private so that you have complete control over where and when it is used. I prefer to use an internal object that I have control.
Lock is an ordinary field. So there is one of it for each instance of 'A'. A.class is global to the whole JVM. So the two blocks have completely different semantics. The version with 'lock' says, 'only one thread can be in this block for this instance of A'. The version with A.class says 'only one thread can be in this block for any instance of A.
In the first case, you synchronize on a public object (A.class), and so other parts of the application might cause problems because they also synchronize on A.class.
In the second case, you synchronize on a private lock object, and are thus sure that nobody else uses the the lock to synchronize access to something else.
Moreover, as indicated in other answers, all the instances of the class will be synchronized on the same lock with the first solution, whereas each instance will have its own lock with the second solution.
The second solution is thus much preferred (although the lock object should be final).
The parameter of synchronized block is needed to be able to create several "named" blocks. So using special lock object is probably more flexible: you can create lock1 and lock2 in future.
Yet another aspect is waiting and notification. You can say lock.wait() and then lock.notfify() from another thread. In this case you can also use both ways (special lock object or A.class as a lock).
I know the difference between synchronized method and synchronized block but I am not sure about the synchronized block part.
Assuming I have this code
class Test {
private int x=0;
private Object lockObject = new Object();
public void incBlock() {
synchronized(lockObject) {
x++;
}
System.out.println("x="+x);
}
public void incThis() { // same as synchronized method
synchronized(this) {
x++;
}
System.out.println("x="+x);
}
}
In this case what is the difference between using lockObject and using this as the lock? It seems to be the same to me..
When you decide to use synchronized block, how do you decide which object to be the lock?
Personally I almost never lock on "this". I usually lock on a privately held reference which I know that no other code is going to lock on. If you lock on "this" then any other code which knows about your object might choose to lock on it. While it's unlikely to happen, it certainly could do - and could cause deadlocks, or just excessive locking.
There's nothing particularly magical about what you lock on - you can think of it as a token, effectively. Anyone locking with the same token will be trying to acquire the same lock. Unless you want other code to be able to acquire the same lock, use a private variable. I'd also encourage you to make the variable final - I can't remember a situation where I've ever wanted to change a lock variable over the lifetime of an object.
I had this same question when I was reading Java Concurrency In Practice, and I thought I'd add some added perspective on the answers provided by Jon Skeet and spullara.
Here's some example code which will block even the "quick" setValue(int)/getValue() methods while the doStuff(ValueHolder) method executes.
public class ValueHolder {
private int value = 0;
public synchronized void setValue(int v) {
// Or could use a sychronized(this) block...
this.value = 0;
}
public synchronized int getValue() {
return this.value;
}
}
public class MaliciousClass {
public void doStuff(ValueHolder holder) {
synchronized(holder) {
// Do something "expensive" so setter/getter calls are blocked
}
}
}
The downside of using this for synchronization is other classes can synchronize on a reference to your class (not via this, of course). Malicious or unintentional use of the synchronized keyword while locking on your object's reference can cause your class to behave poorly under concurrent usage, as an external class can effectively block your this-synchronized methods and there is nothing you can do (in your class) to prohibit this at runtime. To avoid this potential pitfall, you would synchronize on a private final Object or use the Lock interface in java.util.concurrent.locks.
For this simple example, you could alternately use an AtomicInteger rather than synchronizing the setter/getter.
Item 67 of Effective Java Second Edition is Avoid excessive synchronization, thus I would synchronize on a private lock object.
Every object in Java can act as a monitor. Choosing one is dependent on what granularity you want. Choosing 'this' has the advantage and disadvantage that other classes could also synchronize on the same monitor. My advice though is to avoid using the synchronize keyword directly and instead use constructs from the java.util.concurrency library which are higher level and have well defined semantics. This book has a lot of great advice in it from very notable experts:
Java Concurrency in Practice
http://amzn.com/0321349601
In this case it does not matter which object you choose for lock. But you must consistently use the same object for locking to achieve correct synchronization. Above code does not ensure proper synchronization as you once use the 'this' object as lock and next the 'lockObject' as lock.