...
- Subclass the class (trusted code is allowed to subclass the class)
- Create an object of the class (or its superclass, or subclass)
- Access or acquire an object of the class (or its superclass, or subclass)
Furthermore, it is highly recommended that the class's superclasses do not use any synchronization if the private lock object idiom is not being used. If a superclass synchronizes on its this
reference, the subclass should typically synchronize on that same reference instead of synchronizing on its own this
reference. On the other hand, if the superclass uses some other locking strategy, such as an internal private lock , it is still inappropriate for the subclass to synchronize on its this
reference. Sometimes the subclass must use a different lock than the superclass and in these cases, separate internal private locks are the obvious choice for both classesto synchronize shared data, subclasses must also use an internal private lock. However, if it uses intrinsic synchronization over the class object, subclasses may not use intrinsic synchronization over its own class object, unless they explicitly document this locking policy.
Similarly, if a static method is declared synchronized
, the intrinsic lock of the Class object is obtained, and released when the method completes. The same restrictions listed above apply to static methods because any untrusted code that can access an object of the class, or a subclass, can use the getClass()
method to obtain access to the Class object. Reducing the accessibility of the class to package-private may provide some reprieve when using strategies other than internal locking.
...
This noncompliant code example synchronizes on a private but nonfinal non-final field.
Code Block | ||
---|---|---|
| ||
public class SomeObject { private volatile Object lock = new Object(); public void changeValue() { synchronized (lock) { // ... } } public void setLock(Integer lockvaluelockValue) { lock = lockValue; } } |
...
Using a private final lock may only be achieved with block synchronization. Block synchronization is sometimes preferred over method synchronization, because operations that do not require synchronization can be moved outside the synchronized region which reduces the overall execution time. There is no need to declare lock
as volatile because of the strong visibility semantics of final fields. Instead of using setter methods to change the lock, declare and use multiple internal lock objects to achieve the necessary fine-grained locking semantics.
Noncompliant Code Example (static)
...
The untrusted code attempts to acquire a lock on the class object's monitor and upon succeeding, introduces an indefinite delay which holds up the synchronized
changeValue()
method from acquiring the same lock. Note that This noncompliant code example is in compliance with CON32-J. Internally synchronize classes containing accessible mutable static fields. However, the untrusted code also violates CON20-J. Do not perform operations that may block while holding a lock.
...
Using a private lock may only be achieved with block synchronization, as static method synchronization always uses the intrinsic lock of the object's class. HoweverMoreover, block synchronization is also preferred over method synchronization, because it is easy to move operations out of the synchronized block when they might take a long time and they are not truly a critical section.
...