113 lines
2.8 KiB
Plaintext
113 lines
2.8 KiB
Plaintext
== Why is this an issue?
|
|
|
|
A synchronized method is a method marked with the `synchronized` keyword, meaning it can
|
|
only be accessed by one thread at a time. If multiple threads try to access the synchronized method simultaneously, they
|
|
will be blocked until the method is available.
|
|
|
|
Synchronized methods prevent race conditions and data inconsistencies in multi-threaded environments. Ensuring that only one
|
|
thread can access a method at a time, prevents multiple threads from modifying the same data simultaneously, and causing
|
|
conflicts.
|
|
|
|
When one part of a getter/setter pair is `synchronized` the other should be too.
|
|
Failure to synchronize both sides may result in inconsistent behavior at runtime as callers access an inconsistent method state.
|
|
|
|
This rule raises an issue when either the method or the contents of one method in a getter/setter pair are synchronized, but the other is not.
|
|
|
|
== How to fix it
|
|
|
|
Synchronize both `get` and `set` methods by marking the method with the `synchronize` keyword or using a `synchronize` block inside them.
|
|
|
|
=== Code examples
|
|
==== Noncompliant code example
|
|
[source,java,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
public class Person {
|
|
String name;
|
|
int age;
|
|
|
|
public synchronized void setName(String name) {
|
|
this.name = name;
|
|
}
|
|
|
|
public String getName() { // Noncompliant
|
|
return this.name;
|
|
}
|
|
|
|
public void setAge(int age) { // Noncompliant
|
|
this.age = age;
|
|
}
|
|
|
|
public int getAge() {
|
|
synchronized (this) {
|
|
return this.age;
|
|
}
|
|
}
|
|
}
|
|
----
|
|
|
|
==== Compliant solution
|
|
[source,java,diff-id=1,diff-type=compliant]
|
|
----
|
|
public class Person {
|
|
String name;
|
|
int age;
|
|
|
|
public synchronized void setName(String name) {
|
|
this.name = name;
|
|
}
|
|
|
|
public synchronized String getName() {
|
|
return this.name;
|
|
}
|
|
|
|
public void setAge(int age) {
|
|
synchronized (this) {
|
|
this.age = age;
|
|
}
|
|
}
|
|
|
|
public int getAge() {
|
|
synchronized (this) {
|
|
return this.age;
|
|
}
|
|
}
|
|
}
|
|
----
|
|
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html[Oracle Java - Synchronized Methods]
|
|
* https://docs.oracle.com/javase/specs/jls/se20/html/jls-8.html#jls-8.4.3.6[Oracle SE 20 - Synchronized Methods]
|
|
|
|
=== Standards
|
|
|
|
* https://wiki.sei.cmu.edu/confluence/x/4jdGBQ[CERT, VNA01-J.] - Ensure visibility of shared references to immutable objects
|
|
|
|
=== Articles & blog posts
|
|
|
|
* https://web.mit.edu/6.005/www/fa14/classes/18-thread-safety/[MIT - Thread safety]
|
|
* https://www.baeldung.com/java-thread-safety[Baeldung - Thread safety]
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
Synchronize this method to match the synchronization on "[set|get]XXX".
|
|
|
|
|
|
=== Highlighting
|
|
|
|
* Primary: on the method to synchronize
|
|
* Secondary: on the synchronized method
|
|
** message: "[METHOD_NAME]" method.
|
|
|
|
|
|
endif::env-github,rspecator-view[]
|