views:

187

answers:

8

I know when you want to lock method to be executed by only one thread you declare it with synchronized keyword.

What about classes, how to provide a lock on an entire class of objects when a thread is executing some code on an instance of that class?

In other words, when a thread is executing a method on an object, no other thread should be allowed to execute the same method even on a different instance of the same class.

+2  A: 

You could use a static Mutex inside that method. So any concurrent thread is blocking inside the method while another is running it no matter what object of the class it belongs to. I don't think there is any special single keyword to produce the same effect like synchronized.

It is a rather aggressive synchronization, I would avoid it as much as possible.

jdehaan
A: 

There is no built-in mechanism for this. Create your own static lock attribute, and make sure you lock it and unlock it in every method. Don't forget about exceptions - make sure you unlock it in the "finally" sections.

florin
+5  A: 

If you use static synchronized methods, they are locked via the Class Lock. You can also declare a static Object in the class and lock that in a method I believe via something like:

private static final Object STATIC_LOCK = new Object();

private void foo() {
     synchronized (STATIC_LOCK) {
          //do stuff...
     } 
}
SB
A: 

This should work:

public class MyClass {
  void synchronizedMethod() {
    synchronized (MyClass.class) {
       // synchronized on static level
    }
  }
}

Which 'missuses' the class's runtime-representation for locking. This is possible as any object can be used as a mutex in Java.

inflagranti
Given that static synchronized methods synchronise on the class object, why do you consider doing so a misuse?
Pete Kirkham
Is that so? In this case, if the Java designers do it like that, then it is probably no missuse. I thought that the cleanest way was to have a dedicated static Monitor/Mutex object, and that using some object is somewhat a hack - though I would personally opt for that option myself. Put the missuse in quotes now :)
inflagranti
+6  A: 

You synchronize on a specific object, either some designated static lock object, or the class object (which happens when static methods are declared to be synchronized):

class X {
    private static final Object lock = new Object();
    public void oneAtATime() {
        synchronized (lock) {
            // Do stuff
        }
    }
}
class Y {
    public void oneAtATime() {
        synchronized (Y.class) {
            // Do stuff
        }
    }
}

Each variant has its own pros and cons; locking on the class allows other code, outside of the class, to use the same lock for its own reasons (which allows it to orchestrate more high-level synchronization than what you provide) while the static final Object lock approach lets you prohibits it by making the lock field private (which makes it easier to reason about the locking and avoid your code from deadlocking because someone else wrote bad code).

You could of course also use some synchronization mechanism from java.util.concurrent, like explicit Locks, which provide more control over locking (and ReentrantLock currently performs a little better than implicit locks under high contention).


Edit: Note that static/global locks aren't a great way to go - it means every instance of the class ever created will essentially be tied to every other instance (which, aside from making it harder to test or read the code, can severely harm scalability). I assume you do this to synchronize some kind of global state? In that case, I'd consider wrapping that global/static state in a class instead, and implement synchronization per-instance rather than globally.

Instead of something like this:

class Z {
    private static int state;
    public void oneAtATime(){
        synchronized (Z.class) {
            state++;
        }
    }
}

Do it like this:

class State {
    private int value;
    public synchronized void mutate(){ value++; }
}
class Z {
    private final State state;
    public Z(State state){
        this.state = state;
    }
    public void oneAtATime(){
        state.mutate();
    }
}
// Usage:
State s1 = new State(), s2 = new State();
Z foo = new Z(s1);
Z bar = new Z(s1);
Z frob = new Z(s2);
Z quux = new Z(s2);

Now foo and bar are still tied to each other, but they can work independently from frob and quux.

gustafc
This (last) way is almost certainly the best I'd say.It makes it transparent what is supposed to happen with subclasses of your class, and with multiple instances of your program, and also what to be careful of when static methods are needed.
Sanjay Manohar
+2  A: 

Synchronize on static field of your class, or the class itself:

synchronized(MyClass.class) {
        // mutually excluded method body
}
unhillbilly
+1  A: 

Both threads must use this construction

public void someMethod() {
  synchronized(ClassThatShouldBeProtected.class) {
    someSynchronizedCode();
  }
}

This approach benefits from the fact, that class itself is an object and therefore it has a monitor. Then you don't need any artificial static instance.

calavera.info
A: 

http://www.janeg.ca/scjp/threads/synchronization.html

talks about several ways to achieve it. in general, locks are prohibitive and hinder benefits of threading. so the critical code should be minimized as much as its possible.

do you want a class lever lock to access static variables of the class or is it for protecting access to a common external resource the class? in which case you should proly have a separate lock while accessing it.

neal aise