Concurrent Collections
Concurrent Collections#
Concurrent collections are thread-safe data structures that multiple threads can access simultaneously without corruption. Think of them like a shared grocery list that multiple family members can read and update at the same time without anyone seeing incomplete changes—built-in safety mechanisms ensure everyone sees consistent data.
Unlike regular collections that need external locks, concurrent collections handle thread safety internally. This provides better performance and simpler code since you don't need to manage synchronization yourself. Each operation completes atomically, meaning changes either happen completely or not at all.
Common Collection Types#
Hash Maps#
Concurrent hash maps provide thread-safe key-value storage with excellent performance. They divide the internal storage into segments, allowing different threads to work on different segments simultaneously. This means multiple threads can read and write without blocking each other, as long as they're accessing different keys.
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
private final ConcurrentHashMap<String, Integer> cache = new ConcurrentHashMap<>();
public void putValue(String key, Integer value) {
cache.put(key, value);
System.out.println("Stored: " + key + " = " + value);
}
public Integer getValue(String key) {
return cache.get(key);
}
public void atomicUpdate(String key, Integer newValue) {
cache.compute(key, (k, v) -> {
if (v == null) return newValue;
return v + newValue; // Atomic update
});
}
public void printAll() {
cache.forEach((key, value) ->
System.out.println(key + " = " + value));
}
}
import java.util.concurrent.ConcurrentHashMap
class ConcurrentHashMapExample {
private val cache = ConcurrentHashMap<String, Int>()
fun putValue(key: String, value: Int) {
cache[key] = value
println("Stored: $key = $value")
}
fun getValue(key: String): Int? = cache[key]
fun atomicUpdate(key: String, newValue: Int) {
cache.compute(key) { _, v ->
if (v == null) newValue else v + newValue
}
}
fun printAll() {
cache.forEach { (key, value) -> println("$key = $value") }
}
}
TypeScript/JavaScript doesn't support traditional threading or concurrent collections. JavaScript runs in a single-threaded event loop model.
Dart doesn't support traditional threading or concurrent collections. Dart uses isolates with separate memory spaces that communicate via message passing.
Swift can use the third-party SwiftConcurrentCollections library for concurrent hash maps.
// Using SwiftConcurrentCollections library
// Add to Package.swift: .package(url: "https://github.com/peterprokop/SwiftConcurrentCollections.git", from: "1.0.0")
import SwiftConcurrentCollections
let cache = ConcurrentDictionary<String, Int>()
// Thread-safe operations
cache["user_count"] = 100
cache["page_views"] = 5000
if let count = cache["user_count"] {
print("User count: \(count)")
}
// Atomic update
cache.update(key: "user_count") { oldValue in
return (oldValue ?? 0) + 1
}
Python doesn't provide built-in concurrent hash maps. Use synchronization mechanisms like threading.Lock() to protect dictionary access.
Queues#
Concurrent queues maintain FIFO (first-in, first-out) order while allowing multiple threads to add and remove items safely. They're perfect for producer-consumer patterns where some threads generate work items and others process them, without complex coordination code.
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
public class ConcurrentQueueExample {
private final ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
private final BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(10);
public void enqueue(String item) {
queue.offer(item);
System.out.println("Enqueued: " + item);
}
public String dequeue() {
String item = queue.poll();
if (item != null) {
System.out.println("Dequeued: " + item);
}
return item;
}
public void blockingEnqueue(String item) throws InterruptedException {
blockingQueue.put(item);
System.out.println("Blocking enqueued: " + item);
}
public String blockingDequeue() throws InterruptedException {
String item = blockingQueue.take();
System.out.println("Blocking dequeued: " + item);
return item;
}
}
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.BlockingQueue
import java.util.concurrent.ArrayBlockingQueue
class ConcurrentQueueExample {
private val queue = ConcurrentLinkedQueue<String>()
private val blockingQueue = ArrayBlockingQueue<String>(10)
fun enqueue(item: String) {
queue.offer(item)
println("Enqueued: $item")
}
fun dequeue(): String? {
val item = queue.poll()
if (item != null) {
println("Dequeued: $item")
}
return item
}
fun blockingEnqueue(item: String) {
blockingQueue.put(item)
println("Blocking enqueued: $item")
}
fun blockingDequeue(): String {
val item = blockingQueue.take()
println("Blocking dequeued: $item")
return item
}
}
TypeScript/JavaScript doesn't support traditional threading or concurrent collections. JavaScript runs in a single-threaded event loop model.
Dart doesn't support traditional threading or concurrent collections. Dart uses isolates with separate memory spaces that communicate via message passing.
Swift doesn't provide built-in concurrent queues. Use synchronization mechanisms like NSLock or DispatchQueue to protect queue operations, or use DispatchQueue directly for asynchronous task management.
Python provides queue.Queue from the standard library.
import queue
# Thread-safe FIFO queue
task_queue = queue.Queue()
# Enqueue items
task_queue.put("task1")
task_queue.put("task2")
task_queue.put("task3")
# Dequeue item (blocks if queue is empty)
task = task_queue.get()
print(f"Processing: {task}")
task_queue.task_done()
# Non-blocking dequeue
try:
task = task_queue.get_nowait()
print(f"Got: {task}")
except queue.Empty:
print("Queue is empty")
# Check queue size
print(f"Queue size: {task_queue.qsize()}")
Sets#
Concurrent sets ensure unique elements while allowing multiple threads to add, remove, and check for items safely—useful for tracking unique identifiers or filtering duplicate items across threads.
import java.util.concurrent.ConcurrentHashMap;
import java.util.Set;
public class ConcurrentSetExample {
private final Set<String> concurrentSet = ConcurrentHashMap.newKeySet();
public void addItem(String item) {
boolean added = concurrentSet.add(item);
System.out.println("Item " + item + (added ? " added" : " already exists"));
}
public boolean containsItem(String item) {
return concurrentSet.contains(item);
}
public void removeItem(String item) {
boolean removed = concurrentSet.remove(item);
System.out.println("Item " + item + (removed ? " removed" : " not found"));
}
public void printAll() {
System.out.println("Set contents: " + concurrentSet);
}
}
import java.util.concurrent.ConcurrentHashMap
class ConcurrentSetExample {
private val concurrentSet = ConcurrentHashMap.newKeySet<String>()
fun addItem(item: String) {
val added = concurrentSet.add(item)
println("Item $item ${if (added) "added" else "already exists"}")
}
fun containsItem(item: String): Boolean = concurrentSet.contains(item)
fun removeItem(item: String) {
val removed = concurrentSet.remove(item)
println("Item $item ${if (removed) "removed" else "not found"}")
}
fun printAll() {
println("Set contents: $concurrentSet")
}
}
TypeScript/JavaScript doesn't support traditional threading or concurrent collections. JavaScript runs in a single-threaded event loop model.
Dart doesn't support traditional threading or concurrent collections. Dart uses isolates with separate memory spaces that communicate via message passing.
Swift doesn't provide built-in concurrent sets. Use synchronization mechanisms like NSLock or DispatchQueue to protect set operations.
Python doesn't provide built-in concurrent sets. Use synchronization mechanisms like threading.Lock() to protect set operations.
Lists#
Concurrent lists allow multiple threads to add, remove, and read list elements safely. Copy-on-write variants make a new copy when modifying, ensuring readers always see a consistent snapshot—ideal for scenarios where reads vastly outnumber writes.
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.List;
public class ConcurrentListExample {
private final List<String> concurrentList = new CopyOnWriteArrayList<>();
public void addItem(String item) {
concurrentList.add(item);
System.out.println("Added: " + item);
}
public void removeItem(String item) {
boolean removed = concurrentList.remove(item);
System.out.println("Item " + item + (removed ? " removed" : " not found"));
}
public boolean containsItem(String item) {
return concurrentList.contains(item);
}
public void printAll() {
System.out.println("List contents: " + concurrentList);
}
public void safeIteration() {
// Safe to iterate without external synchronization
for (String item : concurrentList) {
System.out.println("Item: " + item);
}
}
}
import java.util.concurrent.CopyOnWriteArrayList
class ConcurrentListExample {
private val concurrentList = CopyOnWriteArrayList<String>()
fun addItem(item: String) {
concurrentList.add(item)
println("Added: $item")
}
fun removeItem(item: String) {
val removed = concurrentList.remove(item)
println("Item $item ${if (removed) "removed" else "not found"}")
}
fun containsItem(item: String): Boolean = concurrentList.contains(item)
fun printAll() {
println("List contents: $concurrentList")
}
fun safeIteration() {
// Safe to iterate without external synchronization
concurrentList.forEach { item -> println("Item: $item") }
}
}
TypeScript/JavaScript doesn't support traditional threading or concurrent collections. JavaScript runs in a single-threaded event loop model.
Dart doesn't support traditional threading or concurrent collections. Dart uses isolates with separate memory spaces that communicate via message passing.
Swift can use the third-party SwiftConcurrentCollections library for concurrent lists.
// Using SwiftConcurrentCollections library
import SwiftConcurrentCollections
let list = ConcurrentArray<String>()
// Thread-safe append
list.append("item1")
list.append("item2")
list.append("item3")
// Thread-safe access
if let first = list.first {
print("First item: \(first)")
}
// Thread-safe iteration
list.forEach { item in
print("Item: \(item)")
}
// Remove element
if let index = list.firstIndex(of: "item2") {
list.remove(at: index)
}
print("List count: \(list.count)")
Python doesn't provide built-in concurrent lists. Use synchronization mechanisms like threading.Lock() to protect list operations.