Thread-Safe Stock Inventory: Buy and Sell Without Overselling
Company: Optiver
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Company: Optiver
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
You are implementing the inventory-management core of a small brokerage service. The service tracks the number of shares of a single stock that are currently available, and it exposes two operations that will be called concurrently from many threads.
Implement a class StockInventory with the following interface:
StockInventory(initial)
— construct the inventory with
initial
shares available.
buy(quantity)
— acquire
quantity
additional shares and add them to the available inventory. A buy always succeeds. Returns the number of shares available immediately after this purchase is applied.
sell(quantity)
— attempt to sell
quantity
shares out of the available inventory. The sale is all-or-nothing: if at least
quantity
shares are available at the moment the sale is applied, deduct exactly
quantity
shares and return
true
; otherwise leave the inventory unchanged and return
false
. Partial fills are not allowed.
Your implementation must remain correct when an arbitrary number of threads call buy and sell simultaneously on the same StockInventory object:
sell
calls must never both succeed if the inventory can only cover one of them.
buy
and every successful
sell
must be reflected exactly once in the inventory. After all threads finish, the final count must equal
initial + (sum of all bought quantities) - (sum of all successfully sold quantities)
.
sell
and the corresponding deduction must happen atomically with respect to all other
buy
and
sell
calls — no other operation may interleave between the check and the update.
You may use the standard synchronization primitives provided by your language's library (mutexes/locks, atomic operations, condition variables, etc.). Keep the critical sections as small as correctness allows.
Single-threaded illustration of the required semantics:
inv = StockInventory(100)
inv.sell(30) -> true (70 shares remain)
inv.sell(80) -> false (only 70 available; inventory unchanged at 70)
inv.buy(50) -> 120 (70 + 50)
inv.sell(120) -> true (0 shares remain)
inv.sell(1) -> false (inventory unchanged at 0)
Under concurrency, any interleaving of the calls is acceptable as long as every individual operation is atomic, the no-overselling invariant holds, and the final count is consistent with the set of operations that succeeded.
0 <= initial <= 10^9
1 <= quantity <= 10^9
for every
buy
and
sell
call
10^5
total operations, issued from up to
64
concurrent threads