Overriding thread-safe methods with methods that are not thread-safe unsafe for concurrent use can result in improper synchronization if the client when a client that depends on the thread-safety promised by the parent inadvertently operates on an instance of the thread-unsafe subclass. An For example, an overridden synchronized method's contract may can be violated if when a subclass provides an implementation that is not safe unsafe for concurrent use. Overriding . Such overriding can easily result in errors that are difficult to diagnose. Consequently, programs must not override thread-safe methods with methods that are not thread-safe is not in itself an error, but is disallowed by this guideline because it may easily lead to errors that are otherwise difficult to diagnoseunsafe for concurrent use.
The locking strategy of classes designed for inheritance should always be documented. This information can subsequently be used to determine an appropriate locking strategy of for subclasses (see CON04 LCK00-J. Use private final lock objects to synchronize classes that may interact with untrusted code and LCK11-J. Avoid client-side locking when using classes that do not commit to their locking strategy).
Noncompliant Code Example (
...
Synchronized Method)
This noncompliant code example overrides the synchronized doSomething() method in the Base class Base with an unsynchronized method in the derived Derived class Derived. :
| Code Block | ||
|---|---|---|
| ||
class Base { public synchronized void doSomething() { // ... } } class Derived extends Base { @Override public void doSomething() { // ... } } |
The doSomething() method of the Base class Base can be safely used by multiple threads. However, but instances of the Derived subclass Derived cannot be safely used by multiple threads.
This programming error can be difficult to diagnose because threads that accept instances of Base can also accept instances of its subclasses. Consequently, clients may could be unaware that the they are operating on a thread-unsafe instance of a subclass of a a thread-safe class.
Compliant Solution (
...
Synchronized Method)
This compliant solution synchronizes the doSomething() method of the subclass. :
| Code Block | ||
|---|---|---|
| ||
class Base { public synchronized void doSomething() { // ... } } class Derived extends Base { @Override public synchronized void doSomething() { // ... } } |
This compliant solution does not violate CON04solution also complies with LCK00-J. Use private final lock objects to synchronize classes that may interact with untrusted code because the accessibility of the class is package-private. Package-private which accessibility is allowable permitted when untrusted code cannot infiltrate the package.
Compliant Solution (
...
Private Final Lock Object)
This compliant solution ensures that the Derived object is class is thread-save safe by overriding the synchronized doSomething() method of the Base class with a method that contains syncrhonizes synchronizes on a private final lock objectsobject.
| Code Block | ||
|---|---|---|
| ||
class Base { public synchronized void doSomething() { // ... } } class Derived extends Base { private final Object lock = new Object(); @Override public void doSomething() { synchronized (lock) { // ... } } } |
This is an acceptable solution, provided that the locking policy of the Derived class provides a consistent locking policyis consistent with that of the Base class.
Noncompliant Code Example (
...
Private Lock)
This noncompliant code example defines a doSomething() method in the Base class Base that uses a private final lock , in accordance with CON04 LCK00-J. Use private final lock objects to synchronize classes that may interact with untrusted code.
| Code Block | ||
|---|---|---|
| ||
class Base { private final Object lock = new Object(); public void doSomething() { synchronized (lock) { // ... } } } class Derived extends Base { Logger logger = // Initialize @Override public void doSomething() { try { super.doSomething(); } finally { logger.log(Level.FINE, "Did something"); } } } |
It is possible that for multiple threads may to cause the entries to be logged in an order that differs from the order in which the tasks are performed. Consequently, The the doSomething() method of the Derived class Derived cannot be used safely used by multiple threads because it is not thread-safe.
Compliant Solution (
...
Private Lock)
This compliant solution solution synchronizes the doSomething() method of the subclass using a its own private final lock object. :
| Code Block | ||
|---|---|---|
| ||
class Base { private final Object lock = new Object(); public void doSomething() { synchronized (lock) { // ... } } } class Derived extends Base { Logger logger = // Initialize private final Object lock = new Object(); @Override public void doSomething() { synchronized (lock) { try { super.doSomething(); } finally { logger.log(Level.FINE, "Did something"); } } } } |
Note that the objects of Base and Derived objects maintain distinct locks that are inaccessible from each othersother's classes. Consequently, Derived can provide thread-safety guarantees independent of Base.
Risk Assessment
Overriding Overriding thread-safe methods with methods that are not thread-safe unsafe for concurrent access can result in unexpected behavior.
Rule | Severity | Likelihood | Detectable |
|---|
Repairable | Priority | Level |
|---|
TSM00-J | Low |
Probable |
Yes |
No | P4 | L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
| Wiki Markup |
|---|
\[[API 06|AA. Java References#API 06]\]
\[[SDN 08|AA. Java References#SDN 08]\] Sun bug database, [Bug ID 4294756|http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4294756] |
Sound automated detection is infeasible; heuristic checks could be useful.
| Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Parasoft Jtest |
| CERT.TSM00.OSNS | Avoid overriding synchronized methods with non-synchronized methods |
Bibliography
...
VOID CON09-J. Do not invoke alien methods that rely on invariants protected by the same lock object 11. Concurrency (CON) CON11-J. Do not assume that declaring an object reference volatile guarantees visibility of its members