synchronized
.xxxxxxxxxx
class MyClassA {
private String value;
public synchronized void foo() { // méthode synchronisée : instance this
setValue(Thread.currentThread().getName() + " : value");
try {
Thread.sleep(1000); // forcer le thread courant à s'endormir pour donner une chance à l'autre thread de s'exécuter.
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getValue());
}
private String getValue() {
return value;
}
private void setValue(String value) {
this.value = value;
}
}
public class LocksSynchronizationTest1 {
public static void main(String[] args) {
final MyClassA myClassA = new MyClassA();
Runnable myRunnable1 = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " (début)");
myClassA.foo(); // le thread courant va acquérir un verrou sur l'instance référée par la variable "myClassA"
System.out.println(Thread.currentThread().getName() + " (fin)");
}
};
Thread myThread1 = new Thread(myRunnable1, "myFirstThread");
Thread myThread2 = new Thread(myRunnable1, "mySecondThread");
myThread1.start();
try {
Thread.sleep(500); // forcer le thread "main" à s'endormir pour être sûr que le thread "myFirstThread" sera exécuté avant le thread "mySecondThread".
} catch (InterruptedException e) {
e.printStackTrace();
}
myThread2.start();
}
}
xxxxxxxxxx
myFirstThread (début)
mySecondThread (début)
myFirstThread : value
myFirstThread (fin)
mySecondThread : value
mySecondThread (fin)
xxxxxxxxxx
class MyClassA {
private String value;
public void foo() {
synchronized (this) // bloc de code synchronisé : instance this
{
setValue(Thread.currentThread().getName() + " : value");
try {
Thread.sleep(1000); // forcer le thread courant à s'endormir pour donner une chance à l'autre thread de s'exécuter.
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getValue());
}
}
private String getValue() {
return value;
}
private void setValue(String value) {
this.value = value;
}
}
Class
;
cette instance est créée automatiquement par la JVM lorsqu'elle charge en mémoire le code source de cette classe en mémoire.T
peut avoir donc deux types d'instances en mémoire :Class
qui représente une classe Java T
est créée automatiquement par la JVM lorsque la classe T
est utilisée pour la déclaration d'une variable.forName
de la classe Class
(Class.forName("T")
).xxxxxxxxxx
class T {
static synchronized void foo() {
// ...
}
void bar() {
synchronized(T.class) {
// ...
}
}
}
T
en utilisant l'opérateur new
(new T()
).xxxxxxxxxx
class R {
synchronized void foo() {
// ...
}
void bar() {
synchronized(this) {
// ...
}
}
}