If I have the following code
class SomeClass {
...
public synchronized methodA() {
....
}
public synchronized methodB(){
....
}
}
This would synchronized on the 'this' object.
However, if my main objective here is to make sure multiple threads don't use methodA (or methodB) at the same time, but they CAN use methodA AND methodB concurrently,
then is this kind of design restrictive? since here thread1 lock the object (monitor object associated with the object) for running methodA but meanwhile thread2 is also waiting on the object lock even though methodA and methodB can run concurrently.
Is this understanding correct?
If yes, is this the kind of situation where we use synchronized block on a private dummy object so that methodA and methodB can run parallely with different thread but not methodA (or methodB) with different threads.
Thanks.
You've answered the question yourself: use one lock object per method and you're safe.
private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
synchronized(lockA){
....
}
}
public void methodB() {
synchronized(lockB){
....
}
}
For more advanced locking mechanisms (e.g. ReentrantLock), read Java Concurrency in Practice by Brian Goetz et al. You should also read Effective Java by Josh Bloch, it also contains some items about using synchronized.
If you want to allow running methodA() and methodB() concurrently but otherwise restrict each method to one thread then you need two separate objects to synchronize on. For instance:
class SomeClass {
private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
synchronized (lockA) {
//
}
}
public void methodB() {
synchronized (lockB) {
//
}
}
}
If my understanding is correct you want to allow thread T1 to run methodA() at the same time thread T2 runs methodB() -- but you don't want thread T1 to run methodA() at the same time thread T2 runs methodA() (and same for methodB) right?
For this scenario you can't use just a simple synchronized method -- instead, as you said, you will need 2 dummy objects (one for methodA and one for methodB) to synchronize on. Or you could use the new Lock class -- one Lock instance per method.
Related
I recently asked about if synchronized methods in Java shared the same lock key. The answer was yes. But the next thought I had was that this pattern is very restrictive and can cause unnecessary delays. For example suppose we have 2 synchronized methods and each of them process different and independent shared variables. What's the point of locking both methods at the same time if the processing of one variable does not affects the other? Is there a way to deal with this situation?
Suppose you have this class:
class C {
public synchronized void foo(...) { ... }
public synchronized void bar(...) { ... }
...
}
And suppose you have:
final C c_0 = new C(...);
final C c_1 = new C(...);
The fact that foo() and bar() both are synchronized does not prevent one thread from calling c_0.foo(...) while another thread simultaneously calls c_1.bar(...). In fact, it does not even prevent one thread from calling c_0.foo(...) while another thread calls c_1.foo(...).
A so-called "synchronized method"
synchronized void foo(...) { ... }
Really is just syntactic sugar for this:
void foo( ... ) {
synchronized(this) {
...
}
}
So, if one thread calls c_0.foo() it's "synchronizing" on the c_0 instance, and if another thread calls c_1.foo(), that thread is synchronizing on the c_1 instance--a different instance.
The synchronized keyword on the foo and bar methods only matters if two different threads both try to operate on the same instance at the same time.
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?
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.
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
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!
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.
I saw this in a tutorial, they asked if there is a problem with the following code. To me it looked like b() cannot be accessed as a() is already having the control over the monitor. Am I right in thinking so?
public class Test {
public synchronized void a() {
b();
System.out.println("I am at a");
}
public synchronized void b() {
System.out.println("I am at b");
}
}
No, there is no problem with that code.
Note two things:
synchronized SomeType foo() { ... } is equivalent to
SomeType foo() {
synchronized (this) { ... }
}
It locks the this instance of the enclosing class. So, in your case a() and b() are locking the same thing
If a thread is already holding a lock on some object's monitor, it prevents another thread from acquiring a lock on the same object, but the same thread can acquire more locks if it needs too, that is not affected. So
public synchronized void a() { // acquires lock on this
b(); // also aquires lock on this, but it's ok because it is the same thread
System.out.println("I am at a");
}
While a thread is inside a(), no other thread will be able to call either a() or b() on the same instance. If they try to, they will have to wait until the current thread exits a(). But the current thread itself is not affected, it can call any synchronized method on this object, because it is already holding the lock.
No, you're incorrect. The thread has control of the monitor, not the method, and so it's capable of following execution into as many methods synchronized on the same object as needed.
I've come across code like the following several times
class Foo {
private Object lock = new Object();
public void doSomething() {
synchronized(lock) {
...
What I'm interested in is why a lock object is created instead of writing synchronized(this)? Is it there to enable sharing the lock? I vaguely remember reading that it is an optimization. Is that true? Also, does it, in some context, make sense to have the lock declared as final?
Synchronizing on this is discouraged because if the object itself is used as a lock from the outside it would break the internal synchronization. Also, remember that synchronized methods are also using this as a lock, which may cause an unwanted effect.
Declaring the lock final is recommended to prevent a situation in which a lock object is reassigned inside a synchronized block, thus causing different threads to see different lock objects. See this other question: Locking on a mutable object - Why is it considered a bad practice?
Imagine a scenario where you have thread1 and thread2 access method1, thread3 and thread4 access method2. Synchronizing on this would block thread3 and thread4 if thread1 or thread2 are accessing method1 which should not happen as thread3 and thread4 have nothing to do with method1. An optimization for this is to use two different locks instead of locking on the whole class instance.
Here is a nice paragraph I found on JavaDoc that reflects this:
Synchronized statements are also useful for improving concurrency with
fine-grained synchronization. Suppose, for example, class MsLunch has
two instance fields, c1 and c2, that are never used together. All
updates of these fields must be synchronized, but there's no reason to
prevent an update of c1 from being interleaved with an update of c2 —
and doing so reduces concurrency by creating unnecessary blocking
Consider using a lock from the java.util.concurrent package
This may provide more optimized locking, for instance - using a ReadWriteLock will let all readers to access without waiting.
Here is the Full working example of "ReentrantReadWriteLock".
public class DataReader {
private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private static final Lock read = readWriteLock.readLock();
private static final Lock write = readWriteLock.writeLock();
public static void loadData() {
try {
write.lock();
loadDataFromTheDB());
} finally {
write.unlock();
}
}
public static boolean readData() {
try {
read.lock();
readData();
} finally {
read.unlock();
}
}
public static List loadDataFromTheDB() {
List list = new ArrayList();
return list;
}
public static void readData() throws DataServicesException {
//Write reading logic
}
}
What is the difference between synchronizing a static method and a non static method in java?Can anybody please explain with an example. Also is there any difference in synchronizing a method and synchronizing a block of code?
I will try and add an example to make this extra clear.
As has been mentioned, synchronized in Java is an implementation of the Monitor concept. When you mark a block of code as synchronized you use an object as a parameter. When an executing thread comes to such a block of code, it has to first wait until there is no other executing thread in a synchronized block on that same object.
Object a = new Object();
Object b = new Object();
...
synchronized(a){
doStuff();
}
...
synchronized(b){
doSomeStuff();
}
...
synchronized(a){
doOtherStuff();
}
In the above example, a thread running doOtherStuff() would block another thread from entering the block of code protecting doStuff(). However, a thread could enter the block around doSomeStuff() without a problem as that is synchronized on Object b, not Object a.
When you use the synchronized modifier on an instance method (a non-static method), it is very similar to having a synchronized block with "this" as the argument. So in the following example, methodA() and methodB() will act the same way:
public synchronized void methodA() {
doStuff();
}
...
public void methodB() {
synchronized(this) {
doStuff();
}
}
Note that if you have a methodC() in that class which is not synchronized and does not have a synchronized block, nothing will stop a thread from entering that method and careless programming could let that thread access non-safe code in the object.
If you have a static method with the synchronized modifier, it is practically the same thing as having a synchronized block with ClassName.class as the argument (if you have an object of that class, ClassName cn = new ClassName();, you can access that object with Class c = cn.getClass();)
class ClassName {
public void static synchronized staticMethodA() {
doStaticStuff();
}
public static void staticMethodB() {
synchronized(ClassName.class) {
doStaticStuff();
}
}
public void nonStaticMethodC() {
synchronized(this.getClass()) {
doStuff();
}
}
public static void unSafeStaticMethodD() {
doStaticStuff();
}
}
So in the above example, staticMethodA() and staticMethodB() act the same way. An executing thread will also be blocked from accessing the code block in nonStaticMethodC() as it is synchronizing on the same object.
However, it is important to know that nothing will stop an executing thread from accessing unSafeStaticMethodD(). Even if we say that a static method "synchronizes on the Class object", it does not mean that it synchronizes all accesses to methods in that class. It simply means that it uses the Class object to synchronize on. Non-safe access is still possible.
In short if you synchronize on a static method you will synchronize on the class (object) and not on an instance (object). That means while execution of a static method the whole class is blocked. So other static synchronized methods are also blocked.
Synchronization in Java is basically an implementation of monitors. When synchronizing a non static method, the monitor belongs to the instance. When synchronizing on a static method, the monitor belongs to the class. Synchronizing a block of code is the same idea, but the monitor belongs to the specified object. If you can get away with it, synchronized blocks are preferable because they minimize the time each thread spends in the critical section
There is virtually no difference between synchronizing a block and synchronizing a method. Basically:
void synchronized m() {...}
is the same as
void m() { synchronized(this) {...} }
By comparison a static synchronized method is the same as:
static void m() { synchronized(MyClass.class) {...} }
Dude, just a hint. Not related to your question:
If any do*Stuff() methods does either
this.a= /*yet another*/ new Object();
or
this.b= /*yet another*/ new Object();
then you are screwed. Because the lock is inside the value, not inside the reference. See Java synchronized references
From javadoc https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
public static synchronized void getInstance(){}
When we acquire a lock on any class, we actually acquire a lock on "Class" class instance which is only one for all instances of class.
public synchronized void getInstance(){}
we can create multiple object's of a class and each object will have one lock associated with it.