メソッドがそのオブジェクトに同期をもたらす前にsynchronize
キーワードを使用することを知っています。つまり、オブジェクトの同じインスタンスを実行している2つのスレッドが同期されます。
ただし、同期はオブジェクトレベルで行われるため、オブジェクトの異なるインスタンスを実行する2つのスレッドは同期されません。メソッドによって呼び出されるJavaクラスに静的変数がある場合、そのクラスのインスタンス間で同期されるようにします。 2つのインスタンスは2つの異なるスレッドで実行されています。
次の方法で同期を実現できますか?
public class Test
{
private static int count = 0;
private static final Object lock= new Object();
public synchronized void foo()
{
synchronized(lock)
{
count++;
}
}
}
静的なオブジェクトlock
を定義し、そのロックにキーワードsynchronized
を使用しているため、クラスcount
のインスタンス間で静的変数Test
が同期されるのは本当ですか?
静的変数へのアクセスを同期するには、いくつかの方法があります。
同期静的メソッドを使用します。これは、クラスオブジェクトで同期します。
public class Test {
private static int count = 0;
public static synchronized void incrementCount() {
count++;
}
}
クラスオブジェクトで明示的に同期します。
public class Test {
private static int count = 0;
public void incrementCount() {
synchronized (Test.class) {
count++;
}
}
}
他の静的オブジェクトで同期します。
public class Test {
private static int count = 0;
private static final Object countLock = new Object();
public void incrementCount() {
synchronized (countLock) {
count++;
}
}
}
方法3は、ロックオブジェクトがクラスの外部に公開されないため、多くの場合に最適です。
単にカウンターを共有する場合は、 AtomicInteger またはJava.util.concurrent.atomicパッケージの別の適切なクラスを使用することを検討してください。
public class Test {
private final static AtomicInteger count = new AtomicInteger(0);
public void foo() {
count.incrementAndGet();
}
}
はい、そうです。
クラスの2つのインスタンスを作成する場合
Test t1 = new Test();
Test t2 = new Test();
次に、t1.fooとt2.fooは両方とも同じ静的オブジェクトで同期するため、互いにブロックします。