Calling a method from within a synchronized method - java

I'm facing a strange problem which has made me wonder what exactly happens in a synchronized method. Let's say there is a method
synchronized public void example(){
//...code
int i=call(); //calling another method
//...do something with i
}
Now while the call() method is being executed, can another object enter this synchronized example() method? So when the call() returns, there might be some ConcurrentModificationException? What to do in order to avoid problems?

No it can't. A synchronized method is basically the same as:
public void example(){
synchronized(this){
//do stuff
}
}

Note that in this example, if call() isn't private or is called from somewhere else in the class, someone else can interrupt what you think is an entirely synchronous process.
synchronized void a(){
println 'hello'
b();
println 'world'
}
void b(){
}
If you expect "everything that a does to be guarded by synchronized", then if b has any side-effects at all, that guarantee is lost if methods other than synchronized void a call b.

When a thread enters a Synchronized method a lock occurs, the lock doesn't release until that method returns, which would be after your call to call().
Here is a good article on locks and synchronization:
http://download.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Related

When do we use Synchronised on a java method that handles 'GET'?

Trying to understand Concurrency Concepts.
I saw a springboot application with a Controller Class that had 2 methods:
#RequestMapping(value = "/r1", produces = "application/json; charset=utf-8", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<> function1(...){...}
and another one in the same class as:
#RequestMapping(value = "/r2", produces = "application/json; charset=utf-8", method = RequestMethod.GET)
#ResponseBody
public synchronized ResponseEntity<>(...){....}
My question is if both methods are in the same class and since a synchronised method locks the whole object of that class, doesn't it lock the non-synchronised method as well?
Question : My question is if both methods are in the same class and since a synchronised method locks the whole object of that class, doesn't it lock the non-synchronised method as well?
Answer : No, Only the synchronized methods will be blocked while all other threads are trying to call synchronized method on same object.
Synchronized Methods From the documentation it is clear, at a time only one thread can execute the synchronized method on object, where all other thread that try executing synchronized method on same object will be blocked.
But still two threads can execute the synchronized method at a time, if they use two different objects
First, it is not possible for two invocations of synchronized methods on the same object to interleave.When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
If you have a synchronized block, you have to give it an object to lock on, like this:
Object o = new Object();
synchronized (o) {
// do something
}
If you want, you could use the object instance itself by using this instead of o, like this:
synchronized (this) {
// do something
}
If you have two methods and you want one lock that protects both methods, you could do this:
Object o = new Object();
public void methodOne() {
synchronized (o) {
// do something
}
}
public void methodTwo() {
synchronized (o) {
// do something
}
}
And like before, you can use this instead of a separate object o, like this:
public void methodOne() {
synchronized (this) {
// do something
}
}
public void methodTwo() {
synchronized (this) {
// do something
}
}
or you can achieve the same thing by marking both of those methods as sychronized, becuase synchronized methods will lock on the object instance:
public synchronized void methodOne() {
// do something
}
public synchronized void methodTwo() {
// do something
}
Non-synchronized methods will not block on anything.

If you have a lock on an object, do you have a lock on all its methods?

Say we have a object foo:
class Foo(){
public synchronized void instanceMethod(){}
}
var foo = new Foo();
if I have a lock on foo:
synchronized(foo){
foo.instanceMethod();
}
do I also have a lock on the instanceMethod() call? Another way of asking the question - if I have a lock on foo, can another thread call foo.instanceMethod() (simultaneously)?
if I have a lock on foo, can another thread call foo.instanceMethod()?
They can call it, but the call will wait until execution leaves your block synchronized on foo, because instanceMethod is synchronized. Declaring an instance method synchronized is roughly the same as putting its entire body in a block synchronized on this.
If instanceMethod weren't synchronized, then of course the call wouldn't wait.
Note, though, that the synchronized block you've shown is unnecessary:
synchronized(foo){ // <==== Unnecessary
foo.instanceMethod();
}
Because instanceMethod is synchronized, that can just be:
foo.instanceMethod();
...unless there's something else in the block as well.
class Foo {
public synchronized void a() { //Do something }
public void b() {
synchronized(this) { // Do something }
}
public void c() { // Do something }
}
Then:
Foo foo = new Foo();
foo.a();
foo.b();
synchronized(foo) { foo.c(); }
All the 3 methods are all pretty much equivalent in terms of synchronization.
There is no such thing as "locking" a method. Locking is done only on objects. Marking a method synchronized simply makes it lock the instance (or its class object for static method).
When you access a method on a locked object, the execution would be blocked as the thread fails to retrieve the monitor for the specified object - that is even before the method has been called. So foo.a() would be blocked when it is getting the foo.
Adding on...
I suddenly remembered something. If you have thread A calling foo.a() and it is taking a very long time to complete, and at that time another thread calls foo.c(), then foo.c() will still be blocked until foo.a() completes.

Java locks with synchronized keyword

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.

Java Monitors - Do synchronised methods prevent any other thread being IN that object?

Does the following mean that only ONE thread can be in ANY method of the object? Or can a multiple threads be in DIFFERENT methods just not the same one? Why?
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
Does the following mean that only ONE thread can be in ANY method of the object?
For your specific example, yes, because all the methods are synchronized and non-static.
If your class had any unsynchronized methods, then the unsynchronized methods would not be blocked.
If your class used synchronized blocks instead of methods and synchronized them on different locks, it could get much more complex.
Does the following mean that only ONE thread can be in ANY method of the object?
Yes. Non-static synchronized methods implicitly synchronize on this. It's equivalent to:
public void increment() {
synchronized(this) {
c++;
}
}
If this were a real piece of code (I know it's not), I would recommend throwing out your SynchronizedCounter class entirely and using AtomicInteger instead.
Of course, they are synchronized on the this object. If you had written your own synchronized block with different objects for the different methods you have then it won't be the case.

difference between synchronizing a static method and a non static method

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.

Categories