Does empty synchronized(this){} have any meaning to memory visibility between threads?

concurrency, java, memory-model, synchronized, volatile

Solution

All writes that occur prior to a `monitor exit` are visible to all threads after a `monitor enter`.

A `synchronized(this){}` can be turned into bytecode like

monitorenter
monitorexit

So if you have a bunch of writes prior to the `synchronized(this){}` they would have occurred before the `monitorexit`.

This brings us to the next point of my first sentence.

visible to all threads after a `monitor enter`

So now, in order for a thread to ensure the writes ocurred it must execute the same synchronization ie `synchornized(this){}`. This will issue at the very least a `monitorenter` and establish your happens before ordering.

So to answer your question

Does an empty synchronized(this) {} block flush all variables changed in current method to "general visible" memory?

Yes, as long as you maintain the same synchronization when you want to read those non-volatile variables.

To address your other questions

what if second thread never calls lock on this? (suppose that second thread reads in other methods). Remember that question is about: flush changes to other threads, not give other threads a way (synchronized) to poll changes made by original thread. Also no-synchronization in other methods is very likely in Spring @PostConstruct context

Well in this case using `synchronized(this)` without any other context is relatively useless. There is no happens-before relationship and it's in theory just as useful as not including it.

is memory visibility of changes forced only in second and subsequent calls by another thread? (remember that this synchronized block is a last call in our method) - this would mark this way of synchronization as very bad practice (stale values in first call)

Memory visibility is forced by the first thread calling `synchronized(this)`, in that it will write directly to memory. Now, this doesn't necessarily mean each threads needs to read directly from memory. They can still read from their own processor caches. Having a thread call `synchronized(this)` ensures it pulls the value of the field(s) from memory and retrieve most up to date value.

Problem

I read this in an upvoted comment on StackOverflow: But if you want to be safe, you can add simple synchronized(this) {} at the end of you @PostConstruct [method] [note that variables were NOT volatile] I was thinking that happens-before is forced only if both write and read is executed in `synchronized` block or at least read is volatile. Is the quoted sentence correct? Does an empty `synchronized(this) {}` block flush all variables changed in current method to "general visible" memory? Please consider some scenerios what if second thread never calls lock on `this`? (suppose that second thread reads in other methods). Remember that question is about: flush changes to other threads, not give other threads a way (synchronized) to poll changes made by original thread. Also no-synchronization in other methods is very likely in Spring `@PostConstruct` context - as original comment says. is memory visibility of changes forced only in second and subsequent calls by another thread? (remember that this synchronized block is a last call in our method) - this would mark this way of synchronization as very bad practice (stale values in first call)

Original source