views:

200

answers:

3

Here's some code I saw once. Can you see what's wrong with it?

[updated]

public class ResourceManager1
{
    private final String mutex = "";
    Object resource = null;

    public Object getResource()
    {
     synchronized (mutex)
     {
      if (resource == null)
      {
       resource = new Object();
      }
     }

     return resource;
    }
}

public class ResourceManager2
{
    private final String mutex = "";
    Object resource = null;

    public Object getResource()
    {
     synchronized (mutex)
     {
      if (resource == null)
      {
       resource = new Object();
      }
     }

     return resource;
    }
}
A: 

mutex is not final and resource is not private.

Besides, you need a getResource method that returns resource, but I suppose this is just a typo.

Dev er dev
+12  A: 

Never synchronize on strings, particularly string literals which are interned. You've basically just got a single lock.

In general, never synchronize on any reference that might be visible outside your class (including "this") unless the purpose of the external visibility is precisely for locking purposes. I usually use a private final variable created solely for the purpose of locking.

Jon Skeet
We have a winner!
fiddlesticks
+1  A: 

You are using the same String as a mutex for both classes and hence only one of the synchronized blocks can be used at a time, which does not seem to be the intention of the code.

lemnisca
It's not the immutability of Strings which is the problem here - it's interning of string literals. Java *could* have kept immutable strings but not done interning, in which case this code would have worked.
Jon Skeet
Ah, true...I knew what I meant but said it badly. Which we all know is not a good thing for a programmer to do, thanks for the correction. :)
lemnisca
yep, could have used mutex = new String("");:)
fiddlesticks