メソッドを processOutbox にしたい場合は、次のキーワードを使用する必要がありますsynchronized
。
public class YourClass{
public synchronized void processOutbox(){
//do all you want
}
}
詳細: https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
コード内に example と呼ばれる YourClass のインスタンスがある場合myInstance
、すべての呼び出しprocessOutbox()
はインスタンス レベルでロックされるため、スレッド セーフになります。
例えば:
YourClass myInstance = new YourClass();
Thread thread1 = new Thread(){
public void run(){
myInstance.processOutbox();
}
}
Thread thread2 = new Thread(){
public void run(){
myInstance.processOutbox();
}
}
thread1.start();
thread2.start();
ここで、thead2 は、thread1 が「processOutbox」への呼び出しを終了するまで待機します。
しかし、例えば:
YourClass myInstance = new YourClass();
YourClass myInstance2= new YourClass();
Thread thread1 = new Thread(){
@Override
public void run(){
myInstance.processOutbox();
}
};
Thread thread2 = new Thread(){
@Override
public void run(){
myInstance2.processOutbox();
}
}
thread1.start();
thread2.start();
thead2 は異なるインスタンスでメソッドを呼び出しているため、待機しません。
誰かが ReentrantLock の使用について具体的に尋ねました -- それで、これは正しいので、これにその応答を追加します。
public class YourClass {
private Lock outboxLock = new ReentrantLock();
public void processOutbox() {
outboxLock.lock()
try {
// do stuff
} finally {
outboxLock.unlock()
}
}
}
これについて特に言及するのは、代わりに tryLock を使用することで、他のスレッドをブロックせずにロックから除外することもできるからです。
public class YourClass {
private Lock outboxLock = new ReentrantLock();
public void processOutbox() {
if( outboxLock.tryLock() ) {
try {
// do stuff
} finally {
outboxLock.unlock()
}
}
}
}