Why not lock one segment, get the subcount, unlock, then move to next segment?
Here’s my take. Suppose 2 threads concurrently inserts an item in each of two segments. Before that, there are 33 items. Afterwards, there are 35 items. So 33 and 35 are both "correct" answers. 34 is incorrect.
If you lock one segment at a time, you could count an old value in one segment then a new value in another segment.
I told Morgan Stanley interviewers that reentrantLock is basically same thing as Synchronized keyword. Basically same thing but with additional features:
- Feature: lockInterruptibly() is very useful if you need to cancel a “grabbing” thread.
- Feature: tryLock() is very useful. It can an optional timeout argument.
Above features all help us deal with deadlock:)
- Feature: Multiple condition variables on the same lock.
- Feature: lock fairness is configurable. A fair lock favors longest-waiting thread. Synchronized keyword is always unfair.
- — query operations —
- Feature: bool hasQueuedThread(targetThread) gives a best-effort answer whether targetThread is waiting for this lock
- Feature: Collection getQueuedThreads() gives a best-effort list of “grabbing” threads on this lock
- Feature: Collection getWaitingThreads (aConditionVar) gives a best-effort view of the given “waiting room”.
- Feature: int getHoldCount() basically gives the “net” re-entrancy count
- Feature: bool isHeldByCurrentThread()
See also https://bintanvictor.wordpress.com/2009/03/21/realtime-inter-vm-communication-in-front-desk-trading-sys/
These are in the QQ category i.e. skills required for QnA IV only.
Q1: 3 threads to print the numbers 1,2,3,4,5… in deterministic, serial order. Just like single-threaded.
Q1b: what if JVM A has T1, T2, and JVM B has T3? How do they coordinate?
%%A: in C++ shared memory is the fastest IPC solution for large data volume. For signaling, perhaps a semaphore or named pipe
%%A: I feel the mutex is probably an kernel object, accessible by multiple processes.
On Windows, mutex, wait handle, … are all accessible cross-process, but java (on Windows or unix) is designed differently and doen’t have these cross-process synchronization devices.
%%A: use a database table with one row one column. Database can notify a JVM.
AA: The java.nio.file package provides a file change notification API, called the Watch Service API. The registered JVM has a thread dedicated to watching.AA: in java, the JDK semaphore is NOT a wrapper of the operation system semaphore so not usable for IPC
A: java Semaphore? Probably not an IPC construct in java.
Q2: have you used any optimized Map implementations outside the JDK?
Q3: to benchmark your various threading solutions how do you remove the random effects of GC and JIT compilation?
%%A: allocate enough memory to avoid GC. Turn off JIT to compile every code path. Perhaps give the JVM some warm-up period to complete the JIT compilation before we start the benchmark.
The factory is recommended, but a true blue ThreadPoolExecutor offers additional methods such as getTaskCount(). See
So in reality I may use the constructor.
My favorite return type is char, largely due to the non-null guarantee.
Callable<ReturnType> must use a reference type. Similar to List<E>.
My suggestion: Callable<Character>. The actual call() method would return a primitive character, so there’s a good-enough guarantee that return value is not null.
Many people ask how to make a child thread’s exception “bubble up” to the parent thread.
Background — A Runnable task is unsure how to handle its own exception. It wants to escalate to parent thread. Note parent has to block for the entire duration of the child thread (right after child’s start()), blocked either in wait() or some derivative of wait().
This question is not that trivial. Here are my solutions:
1) Callable task and Futures results — but is the original exception escalated? Yes. P197 [[java threads]]
2) Runnable’s run() method can temporarily catch the exception, save the object in a global variable such as a blocking queue, and notifyAll(). Parent thread could check the global variable after getting notified. Any thread can monitor the gloabal.
If you don’t have to escalate to parent thread, then
3) setUncaughtExceptionHandler() – I think the handler method is called in the same exception thread — single-threaded. In the handler, you can give the task to a thread pool, so the exception thread can exit, but I don’t know how useful.
4) adopt invokeAndWait() design — invokeAndWait() javadoc says “Note that if the Runnable.run() method throws an uncaught exception (on EDT) it’s caught and rethrown, as an InvocationTargetException, on the callers thread”
In c#, there are various constructs similar to Futures.get() — seems to be the standard solutions for capturing child thread exception.
* Task.Result property
Cancellation is required when you decide a target thread should be told to stop.
Cancellation is a practical technique, too advanced for most IV.
Note in both java and c#, cancellation is cooperative. The requester (on it’s own thread) can’t force the target thread to stop.
C# has comprehensive support for thread cancellation (CancellationToken etc). Java uses a numbers of simpler constructs, described concisely in [[thinking in java]].
* loop polling – the preferred method if your design permits.
* thread pool shutdown, which calls thread1.interrupt(), thread2.interrupt() …
* Future — myFuture.cancel(true) can call underlyingThread.interrupt()
Some blocking conditions are clearly interruptible — indicated by the compulsory try block surrounding the wait() and sleep(). Other blocking conditions are immune to interrupt.
NIO is interruptible but the traditional I/O isn’t.
The new Lock objects supports lockInterruptibly(), but the traditional synchronized() lock grab is immune to interrupt.