Title here
Summary here
In the previous example we saw how to manage simple counter state using atomic operations. For more complex state we can use a mutex to safely access data across multiple threads.
import java.util.concurrent.locks.ReentrantLock
class Container {
private final ReentrantLock lock = new ReentrantLock()
private Map<String, Integer> counters = [:]
// Lock the mutex before accessing `counters`; unlock
// it at the end of the method using a try-finally block.
void inc(String name) {
lock.lock()
try {
counters[name] = (counters[name] ?: 0) + 1
} finally {
lock.unlock()
}
}
}
// Note that the ReentrantLock is initialized in the constructor,
// so no additional initialization is required here.
def c = new Container(counters: ["a": 0, "b": 0])
// This closure increments a named counter in a loop.
def doIncrement = { String name, int n ->
n.times { c.inc(name) }
}
// Run several threads concurrently; note
// that they all access the same Container,
// and two of them access the same counter.
def threads = [
Thread.start { doIncrement("a", 10000) },
Thread.start { doIncrement("a", 10000) },
Thread.start { doIncrement("b", 10000) }
]
// Wait for the threads to finish
threads*.join()
println c.counters
Running the program shows that the counters updated as expected.
$ groovy mutexes.groovy
[a:20000, b:10000]
Next we’ll look at implementing this same state management task using only threads and message passing.
In this Groovy example:
ReentrantLock
instead of sync.Mutex
for thread synchronization.Container
class encapsulates the lock and the counters.doIncrement
instead of a function for the incrementing logic.Thread.start
is used to create and start threads, replacing Go’s goroutines.threads*.join()
to wait for all threads to complete, which is equivalent to WaitGroup
in Go.This translation maintains the core concepts of the original Go code while adapting to Groovy’s syntax and concurrency model.