dumdum
dumdum

Reputation: 55

if i have two methods that cannot happen simultaneously in one class on separate threads, how to lock it?

If I have a class that has 2 methods say setA and setB that have synchronized but they are not synchronized on the same object, how do I lock it such that if there were two instances of the class, methods setA and setB cannot happen simultaneously?

Upvotes: 0

Views: 88

Answers (4)

vnagy
vnagy

Reputation: 1085

In short, you can use a synchronized (lockObj) {...} block in the body of both methods, and use the same lockObj instance.

class MyClass {
    private final Object lock;

    public MyClass(Object lock) {
        this.lock = lock;
    }

    public void setA() {
        synchronized (lock) {
            //...
        }
    }
    public void setB() {
        synchronized (lock) {
            //...
        }
    }
}

Few things to note:

  • The lock needs not to be static. It is up to your implementation how you provide it. But every MyClass instance must use the same lock instance if you want them to prevent threads from executing their blocks simultaneously.
  • You can not use synchronized methods in this case, since each non static synchronized method will use its on this instance's monitor.
  • If you want to access other instance members, you can not use static synchronized methods either.

Upvotes: 1

yshavit
yshavit

Reputation: 43456

Synchronize them on a single, static reference. A private static final Object lock = new Object () will do, as Will just TheClass.class.

This will also mean that no two threads can invoke setA at the same time, even if nobody is invoking setB. If that's not acceptable, you can use a (static) read-write lock for finer-grained access. setA uses the read lock, and setB uses the write lock; that means that any number of threads can invoke setA, but only one can invoke setB. You probably don't want the reverse to also be true, because that's susceptible to deadlocking.

Upvotes: 0

pczeus
pczeus

Reputation: 7868

Multiple ways.

1) You can synchronize the methods: public synchronized void setA() Doing that means that only one thread can enter the method at a time (good and bad)

2) A better solution would be to use a ReentrantLock:

ReentrantLock lock = new ReentrantLock();
void public void setA() {
    lock.lock();
    try {
        //Do Something
    } 
    finally {
        lock.unlock();
    }
}

There are other ways as well. You can check the Java tutorial on concurrency: https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Another decent posting: http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/

Good luck!

Upvotes: 0

Miles
Miles

Reputation: 110

You can still synchronize on another object within the class that you create.

Object lock = new Object();

Then just synchronize on the lock object.

If you want to get a bit more into it you can use the util.concurrency libraries. Check out Semaphores or Latches, depends on what you want to do with your setA and setB

Upvotes: 0

Related Questions