Synchronized (Groovy 5.0.7)

Package: groovy.transform

## [Java] Annotation Type Synchronized

- groovy.transform.Synchronized

-     @Documented
      @Retention(RetentionPolicy.SOURCE)
      @Target(ElementType.METHOD)
      @GroovyASTTransformationClass("org.codehaus.groovy.transform.SynchronizedASTTransformation")
      public @interface Synchronized

  Method annotation to make a method call synchronized for concurrency handling with some useful baked-in conventions.

  `@Synchronized` is a safer variant of the `synchronized` method modifier. The annotation can only be used on static and instance methods. It operates similarly to the `synchronized` keyword, but it locks on different objects. When used with an instance method, the `synchronized` keyword locks on `this`, but the annotation locks on a (by default automatically generated) field named `$lock`. If the field does not exist, it is created for you. If you annotate a static method, the annotation locks on a static field named `$LOCK` instead.

  If you want, you can create these locks yourself. The `$lock` and `$LOCK` fields will not be generated if you create them yourself. You can also choose to lock on another field, by specifying its name as parameter to the `@Synchronized` annotation. In this usage variant, the lock field will not be created automatically, and you must explicitly create it yourself.

  Rationale: Locking on `this` or your own class object can have unfortunate side effects, as other code not under your control can lock on these objects as well, which can cause race conditions and other nasty threading-related bugs.

  Example usage:

       class SynchronizedExample {
         private final myLock = new Object()

         @Synchronized
         static void greet() {
           println "world"
         }

         @Synchronized
         int answerToEverything() {
           return 42
         }

         @Synchronized("myLock")
         void foo() {
           println "bar"
         }
       }

  which becomes:

       class SynchronizedExample {
         private static final $LOCK = new Object[0]
         private final $lock = new Object[0]
         private final myLock = new Object()

         static void greet() {
           synchronized($LOCK) {
             println "world"
           }
         }

         int answerToEverything() {
           synchronized($lock) {
             return 42
           }
         }

         void foo() {
           synchronized(myLock) {
             println "bar"
           }
         }
       }

  Credits: this annotation is inspired by the Project Lombok annotation of the same name. The functionality has been kept similar to ease the learning curve when swapping between these two tools.

  Details: If `$lock` and/or `$LOCK` are auto-generated, the fields are initialized with an empty `Object[]` array, and not just a new `Object()` as many snippets using this pattern tend to use. This is because a new `Object` is NOT serializable, but a 0-size array is. Therefore, using `@Synchronized` will not prevent your object from being serialized.

  More examples:

       import groovy.transform.Synchronized

       class Util {
           private counter = 0

           private def list = ['Groovy']

           private Object listLock = new Object[0]

           @Synchronized
           void workOnCounter() {
               assert 0 == counter
               counter++
               assert 1 == counter
               counter --
               assert 0 == counter
           }

           @Synchronized('listLock')
           void workOnList() {
               assert 'Groovy' == list[0]
               list << 'Grails'
               assert 2 == list.size()
               list = list - 'Grails'
               assert 'Groovy' == list[0]
           }
       }

       def util = new Util()
       def tc1 = Thread.start {
           100.times {
               util.workOnCounter()
               sleep 20
               util.workOnList()
               sleep 10
           }
       }
       def tc2 = Thread.start {
           100.times {
               util.workOnCounter()
               sleep 10
               util.workOnList()
               sleep 15
           }
       }
       tc1.join()
       tc2.join()

  Since:
    1.7.3

- - ### Element Summary

    Optional Element Summary
    Type | Name and Description
    --- | ---
    `String` | `value` Returns: if a user specified lock object with the given name should be used Default: ""

  - ### Inherited Methods Summary

    Inherited Methods
    Methods inherited from class | Name
    --- | ---
    `class Object` | `equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Element Detail

    - #### public String value

      Returns:
        if a user specified lock object with the given name should be used
      Default:
        ""