Synchronization under covers - java

I was trying to dive into synchronization.
here, its mentioned "Every object has an intrinsic lock associated with it.".
I understand Object class. Its ( quite known to us ) does not have any property like a lock ( thus i guess its called intrinsic lock ). What exactly is this lock (ie is it a Lock.java class ? it is some sort of hidden field ? ) and how is it associated with an object (ie is there some mystery implicit reference to the lock from an object, something happening natively ) ?
When several threads try to acquire the same lock, one or more threads will be suspended and they will be resumed later. Well where are these threads stored ? What data structure keeps records of waiting threads ?
What logic is used under the covers to pick a thread waiting to enter synchronized method, when there are many waiting ?
Any reference to what happens under the covers (step by step) from "synchronized keyword" to "intrinsic lock aquisition" ?
Is there an upper limit on number of threads that are allowed to wait on synchronized ?

1) Yes, the lock is essentially a hidden field on the object. You can't access it except through synchronization.
2) Waiting threads essentially just sleep until the lock is available. They aren't "stored" anyplace special, nor is there a visible queue of waiting threads. Details of implementation are hidden.
3) I don't think there's any promised order. If you explicitly need round-robin scheduling or prioritization or something of that sort, it's your responsibility to implement it (or use a class which implements it for you) on top of the synchronization lock mechanism.
4) This is likely to be handled as an OS semaphore, if you understand those. If you don't, defining them strikes me as too much detail to be addressed properly here... and you don't really need to understand this unless you're reimplementing it.
5) There is no explicit limit, as far as I know. (I haven't checked the official Java Specification, but I understand how this kind of thing gets implemented at the OS level.) Of course at some point you're going to run out of system resources, but I think you'll generally run out of other resources (like memory to run those threads in) first.
One additional note: It's also worth looking at the Atomic... classes. When these can be used, they will be somewhat more efficient in modern processors than traditional Java synchronization can be.

Related

How do conventional locks protect from parallel access in Java?

One of the first things we all learnt about concurrency in Java is that we use locks (synchronized keyword, Lock/ReadWriteLock interface) to protect against concurrent access. For example:
synchronized void eat(){
//some code
}
In theory, this method eat() can be executed by a single thread. Even though there are many threads waiting to execute it, only one will take the lock. But then comes parallelism, which made me think twice about what I just said.
I have 4 core CPU. That means I can do 4 tasks parallelly. Yes, lock can be taken by a single thread. But could it happen that 4 threads call method eat() and take a lock at the LITERALLY same time, although there is a lock that needs to be acquired to actually do anything?
Can something like that even happen in Java? I guess it can't but I had to ask this. And how is it even dealing with a case I just said?
...4 threads...take a lock at the LITERALLY same time...
Can't happen. Any "synchronized" operation (e.g., "take a lock") must operate on the system's main memory, and in any conventional computer system, there is only one memory bus. It is physically impossible for more than one CPU to access the main memory at the same time.
If two CPUs decide to access the memory at literally the same time, the hardware guarantees that one of them will "win" the race and go first, while the other one is forced to wait its turn.
Short answer - JVM keeps a list of threads that are trying to get the lock.
More details
https://wiki.openjdk.java.net/display/HotSpot/Synchronization
Also, worth mentioning that list (aka "inflated lock") is only created when really required (== when contention on a lock happens).

Mutex Locks vs Peterson's Algorithm?

Do mutex locks ensure bounded waiting condition ? Is it possible if two threads are trying to get hold of a lock, but only one process (just by luck) gets it again and again. Since Peterson's Algorithm ensures bounded waiting, is it better to use that instead of mutex locks ?
It is possible to have unbounded wait with mutices, if for instance locking attempts keep coming in on a mutex, at least in C++ std::mutex there's no guaranteed first comes first gets.
However this shouldn't really be a concern - Unless you have some lock with many many threads locking all the time (and even in that case it's very unlikely to cause some starvation situation).
The best thing to do is always use standard library locking mechanism and not write your own mutices.
Mutex with "bounded waiting condition" is called Fair sometimes. As gbehar correctly mention above, C++ standard doesn't define fairness for std::mutex. If you really need fair mutex, you can look at Intel TBB, where fairness is guaranteed for some kinds of them. I would like to remember that fairness comes not without overhead.
See https://www.threadingbuildingblocks.org/docs/help/tbb_userguide/Mutex_Flavors.html for details.
Update: Current link https://github.com/oneapi-src/oneTBB/blob/master/doc/main/tbb_userguide/Mutex_Flavors.rst

Does jvm guarantie update of processor cache after switching threads?

I was asked by interviewer is there any danger not to use volatile if we know for sure that threads will never interfere.
eg. we have:
int i = 10;
// Thread 1
i++;
// await some time and switch to Thread 2
getI();
I don't use any synchronization.
Do we have any danger to receive outdated value of i by second thread?
Without volatile or synchronized or read/write barrier, there is no guarantee that another thread will ever see a change you made, no matter how long your wait. In particular boolean fields can be inlined into the code and no read actually performed. In theory, int values could be inlined if the JVM detects the field is not changed by the thread (I don't believe it actually does though)
we know for sure that threads will never interfere.
This is not something you can know, unless the reading thread is not running when you perform the update. When thread starts it will see any changes which occurred before it started.
You might receive outdated values, yes.
The reason in short is:
Every thread in Java has its own little 'cache'. For performance reasons, threads keep a copy of the 'master' data in their own memory. So you basically have a main memory and a threadlocal one. The volatile keyword forces the thread to access the main memory and not its local one.
Refer to this for more information: http://www.ibm.com/developerworks/library/j-5things15/
If an interviewer asked me that question, I would answer in terms of the Java Language Specification. There is no "cache" or "main memory" in the JLS. The JLS talks about fields (a.k.a., instance variables and class variables) and it makes very specific guarantees about when an update to a field that happens in thread A will become visible in thread B. Implementation details like "cache" and "memory barriers" and can vary from one platform to another, but a program that is correct with respect to the JLS should (in theory) be correct on any Java platform.

What's the meaning of an object's monitor in Java? Why use this word?

When reading articles about Java threads, I often notice the expression: "current thread is the owner of this object's monitor". I get the meaning: the thread gets the right to operate on the object. But I am puzzled why we use the phrase "the object's monitor" instead of "the object's lock"?
In brief, I don't know the meaning of the word 'monitor'
The question may be strange and simple. But I wish anybody can help to solve it. 3ks
but I am puzzled why use word "the object's monitor" instend of "the object's lock"?
See ulmangt's answer for links that explain the term "monitor" as used in this context. Note that:
"Monitors were invented by Per Brinch Hansen and C. A. R. Hoare, and were first implemented in Brinch Hansen's Concurrent Pascal language."
(Source: Wikipedia)
Why use the term "monitor" rather than "lock"? Well strictly speaking, the terms do mean different things ... especially if you use them in the way that they were originally intended to be used.
A "lock" is something with acquire and release primitives that maintain certain lock properties; e.g. exclusive use or single writer / multiple reader.
A "monitor" is a mechanism that ensures that only one thread can be executing a given section (or sections) of code at any given time. This can be implemented using a lock (and "condition variables" that allow threads to wait for or send notifications to other threads that the condition is fulfilled), but it is more than just a lock. Indeed, in the Java case, the actual lock used by a monitor is not directly accessible. (You just can't say "Object.lock()" to prevent other threads from acquiring it ... like you can with a Java Lock instance.)
In short, if one were to be pedantic "monitor" is actually a better term than "lock" for characterizing what Java is providing. But in practice, both terms are used almost interchangeably.
A monitor is simply a term for an object whose methods can be safely used in a multithreaded environment.
There's a great Wikipedia article on Monitors:
http://en.wikipedia.org/wiki/Monitor_(synchronization)
If you scroll down, it's even got a section explicitly about Java.
Quote from Inside the Java Virtual Machine
A thread in the Java virtual machine requests a lock when it arrives
at the beginning of a monitor region. In Java, there are two kinds of
monitor regions: synchronized statements and synchronized methods.
Monitor
A monitor is like a building that contains one special room that can
be occupied by only one thread at a time. The room usually contains
some data. From the time a thread enters this room to the time it
leaves, it has exclusive access to any data in the room. Entering the
monitor building is called "entering the monitor." Entering the
special room inside the building is called "acquiring the monitor."
Occupying the room is called "owning the monitor," and leaving the
room is called "releasing the monitor." Leaving the entire building is
called "exiting the monitor."
In addition to being associated with a bit of data, a monitor is
associated with one or more bits of code, which in this book will be
called monitor regions.
As mentioned earlier, the language provides two built-in ways to
identify monitor regions in your programs: synchronized statements and
synchronized methods. These two mechanisms, which implement the mutual
exclusion aspect of synchronization, are supported by the Java virtual
machine's instruction set.
Lock
To implement the mutual exclusion capability of monitors, the Java
virtual machine associates a lock (sometimes called a mutex) with each
object and class. A lock is like a privilege that only one thread can
"own" at any one time.
A single thread is allowed to lock the same object multiple times. For
each object, the Java virtual machine maintains a count of the number
of times the object has been locked. An unlocked object has a count of
zero. When a thread acquires the lock for the first time, the count is
again incremented to one. Each time the thread acquires a lock on the
same object, the count is again incremented.
A synchronized block around an object is its monitor, which controls a lock on the object. Here an example
synchronized (object) {
while (<condition does not hold>)
object.wait(timeout);
... // Perform action appropriate to condition
}
The Java Virtual Machine uses monitors to support multithreading. Monitors achieve this through two concepts - Mutual exclusion while running the threads (here is where 'locking' comes into picture) and coordination as a means of inter thread communication (here is where object's wait and notify methods come into picture).
Reading the following part from "Inside JVM" will clear this doubt, is it very nicely explained over here (Chapter 20, Thread synchronization) -
https://www.artima.com/insidejvm/ed2/threadsynchP.html
Even though it is late to answer this question, I thought to just add in-case it is useful.
Here is a synchronized block of Java code inside an unsynchronized Java method
public void add(int value){
synchronized(this){
this.count += value;
}
}
In the example "this" is used, which is the instance the add method is called on.
A synchronized instance method uses the object it belongs to as monitor object.
=> Only one thread can execute inside a Java code block synchronized on the same monitor object.

Some questions on java multithreading,

I have a set of questions regarding Java multithreading issues. Please provide me with as much help as you can.
0) Assume we have 2 banking accounts and we need to transfer money between them in a thread-safe way.
i.e.
accountA.money += transferSum;
accountB.money -= transferSum;
Two requirements exist:
no one should be able to see the intermediate results of the operation (i.e. one acount sum is increased, but others is not yet decreased)
reading access should not be blocked during the operation (i.e. old values of account sums should be shown during the operation goes on)
Can you suggest some ideas on this?
1) Assume 2 threads modify some class field via synchronized method or utilizing an explicit lock. Regardless of synchronization, there are no guarantee that this field will be visible to threads, that read it via NOT synchronized method. - is it correct?
2) How long a thread that is awoken by notify method can wait for a lock? Assume we have a code like this:
synchronized(lock) {
lock.notifyall();
//do some very-very long activity
lock.wait() //or the end of synchronized block
}
Can we state that at least one thread will succeed and grab the lock? Can a signal be lost due to some timeout?
3) A quotation from Java Concurrency Book:
"Single-threaded executors also provide sufficient internal synchronization to guarantee that any memory writes made by tasks are visible to subsequent tasks; this means that objects can be safely confined to the "task thread" even though that thread may be replaced with another from time to time."
Does this mean that the only thread-safety issue that remains for a code being executed in single-threaded executor is data race and we can abandon the volatile variables and overlook all visibility issues? It looks like a universal way to solve a great part of concurrency issues.
4) All standard getters and setters are atomic. They need not to be synchronized if the field is marked as volatile. - is it correct?
5) The initiation of static fields and static blocks is accomplished by one thread and thus need not to be synchronized. - is it correct?
6) Why a thread needs to notify others if it leaves the lock with wait() method, but does not need to do this if it leaves the lock by exiting the synchronized block?
0: You can't.
Assuring an atomic update is easy: you synchronize on whatever object holds the bank accounts. But then you either block all readers (because they synchronize as well), or you can't guarantee what the reader will see.
BUT, in a large-scale system such as a banking system, locking on frequently-accessed objects is a bad idea, as it introduces waits into the system. In the specific case of changing two values, this might not be an issue: it will happen so fast that most accesses will be uncontended.
There are certainly ways to avoid such race conditions. Databases do a pretty good job for ba nk accounts (although ultimately they rely on contended access to the end of a transaction).
1) To the best of my knowledge, there are no guarantees other than those established by synchronized or volatile. If one thread makes a synchronized access and one thread does not, the unsynchronized access does not have a memory barrier. (if I'm wrong, I'm sure that I'll be corrected or at least downvoted)
2) To quote that JavaDoc: "The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object." If you decide to throw a sleep into that synchronized block, you'll be unhappy.
3) I'd have to read that quote several times to be sure, but I believe that "single-threaded executor" is the key phrase. If the executor is running only a single thread, then there is a strict happens-before relationship for all operations on that thread. It does not mean that other threads, running in other executors, can ignore synchronization.
4) No. long and double are not atomic (see the JVM spec). Use an AtomicXXX object if you want unsynchronized access to member variables.
5) No. I couldn't find an exact reference in the JVM spec, but section 2.17.5 implies that multiple threads may initialize classes.
6) Because all threads wait until one thread does a notify. If you're in a synchronized block, and leave it with a wait and no notify, every thread will be waiting for a notification that will never happen.
0) Is a difficult problem because you don't want intermediate results to be visible or to lock readers during the operation. To be honest I'm not sure it's possible at all, in order to ensure no thread sees intermediate results you need to block readers while doing both writes.
If you dont want intermediate results visible then you have to lock both back accounts before doing your writing. The best way to do this is to make sure you get and release the locks in the same order each time (otherwise you get a deadlock). E.G. get the lock on the lower account number first and then the greater.
1) Correct, all access must be via a lock/synchronized or use volatile.
2) Forever
3) Using a Single Threaded Executor means that as long as all access is doen by tasks run by that executor you dont need to worry about thread safety/visibilty.
4) Not sure what you mean by standard getters and setters but writes to most variable types (except double and long) are atomic and so don't need sync, just volatile for visibility. Try using the Atomic variants instead.
5) No, it is possible for two threads to try an init some static code, making naive implementations of Singleton unsafe.
6) Sync and Wait/Notify are two different but related mechanisms. Without wait/notify you'd have to spin lock (i.e. keep getting a lock and polling )on a object to get updates
5) The initiation of static fields and static blocks is accomplished by one thread and thus need not to be synchronized. - is it correct?
VM executes static initialization in a synchronized(clazz) block.
static class Foo {
static {
assert Thread.holdsLock(Foo.class); // true
synchronized(Foo.class){ // redundant, already under the lock
....
0) The only way I can see to do this to to store accountA and accountB in an object stored in an AtomicReference. You then make a copy of the object, modify it, and update the reference if it is still the same as the original reference.
AtomicReference<Accounts> accountRef;
Accounts origRef;
Accounts newRef;
do {
origRef = accountRef.get();
// make a deep copy of origRef
newRef.accountA.money += transferSum;
newRef.accountB.money -= transferSum;
} while(accountRef.compareAndSet(origRef, newRef);

Categories

Resources