When we write applications with concurrency needs we can use the ReentrantReadWriteLock
class to specify a lock on specific methods. Normally we have to add a field to our class of the type ReentrantReadWriteLock
and then write code to get a read lock or write lock, do our stuff and finally release the lock again. Since Groovy 1.8 we can use the AST transformation annotations duo WithReadLock
and WithWriteLock
. Groovy will add a lock field and adds the code to acquire and release the locks again in our compiled class file. We don't have to write this code ourselves anymore.
import groovy.transform.* class Bucket { final def items = [] @WithWriteLock void add(String item) { items << item } @WithReadLock List getAllItems() { items } } def bucket = new Bucket() // Create read/write threads that use the same // bucket instance. def allThreads = [] 3.times { allThreads << Thread.start { 5.times { bucket.add Thread.currentThread().name + ': Groovy rocks' println "> ${Thread.currentThread().name} adds item to bucket." sleep 100 } } allThreads << Thread.start { 3.times { int numberOfItems = bucket.allItems.size() println "< ${Thread.currentThread().name} says $numberOfItems items are in the bucket." sleep 150 } } } allThreads.each { it.join() } assert bucket.items.size() == 15 println bucket.items
The following output shows the results of running the code. This output will be different each time we run the code.
> Thread-482 adds item to bucket. < Thread-483 says 1 items are in the bucket. > Thread-484 adds item to bucket. < Thread-485 says 2 items are in the bucket. > Thread-486 adds item to bucket. < Thread-487 says 3 items are in the bucket. > Thread-482 adds item to bucket. > Thread-484 adds item to bucket. > Thread-486 adds item to bucket. < Thread-483 says 6 items are in the bucket. < Thread-485 says 6 items are in the bucket. < Thread-487 says 6 items are in the bucket. > Thread-482 adds item to bucket. > Thread-484 adds item to bucket. > Thread-486 adds item to bucket. > Thread-482 adds item to bucket. < Thread-483 says 10 items are in the bucket. > Thread-484 adds item to bucket. < Thread-485 says 11 items are in the bucket. > Thread-486 adds item to bucket. < Thread-487 says 12 items are in the bucket. > Thread-482 adds item to bucket. > Thread-484 adds item to bucket. > Thread-486 adds item to bucket. [Thread-482: Groovy rocks, Thread-484: Groovy rocks, Thread-486: Groovy rocks, Thread-482: Groovy rocks, Thread-484: Groovy rocks, Thread-486: Groovy rocks, Thread-482: Groovy rocks, Thread-484: Groovy rocks, Thread-486: Groovy rocks, Thread-482: Groovy rocks, Thread-484: Groovy rocks, Thread-486: Groovy rocks, Thread-482: Groovy rocks, Thread-484: Groovy rocks, Thread-486: Groovy rocks]
The annotations also accept a name of an explicit lock field we have defined in our class ourselves. So we can use multiple locks within the same class.