Concurrency

Notes on Double-Checked Locking and 32-bit primitive values

To lazily initialize a variable of a reference type in a multithreaded environment, we either use the Initialization-On-Demand Holder or use the Double-Checked Locking with the variable being qualified by the volatile keyword. The variable does not need to be qualified by volatile if it is a 32-bit primitive such as int and float.

Queue latency benchmark: the Disruptor style vs the ArrayBlockingQueue style

Queue latency is the main performance metric that Disruptor sets itself apart from traditional queue implementations, e.g., ArrayBlockingQueue. To my understanding, Disruptor is based on volatile variable polling, rather than the blocking wait() and notify() mechanism. In this post, we benchmark the Disruptor polling style and the ArryaBlockingQueue blocking style using a simple queue with just one producer and one consumer. We define two latency metrics: one is the latency between a producer starts producing an item and ends producing the item, i.e., the producing latency; the other is the latency between a producer starts producing an item and a consumer starts consuming the same item, i.e., the queue latency. By definition, the queue latency includes the producing latency.