これは、このリンクで見つけたテキストです。
「静的メソッドのロックを避ける
最悪の解決策は、静的メソッドに「同期」キーワードを配置することです。これは、このクラスのすべてのインスタンスをロックすることを意味します。」
静的メソッドを同期すると、クラスのすべてのインスタンスがロックされるのはなぜですか? クラスをロックするだけではいけませんか?
これは、このリンクで見つけたテキストです。
「静的メソッドのロックを避ける
最悪の解決策は、静的メソッドに「同期」キーワードを配置することです。これは、このクラスのすべてのインスタンスをロックすることを意味します。」
静的メソッドを同期すると、クラスのすべてのインスタンスがロックされるのはなぜですか? クラスをロックするだけではいけませんか?
これを理解する最も簡単な方法は、インスタンス メソッドと静的メソッドに対してロックがどのように機能するかを比較することです。次の 2 つのメソッドを持つ Test.java クラスがあるとします。
public class Test{
public synchronized void instanceMethod(){
}
public synchronized static void staticMethod(){
}
}
一方、クラス Test には、testA と testB の 2 つのインスタンスがあります。また、クラス Test に並行してアクセスしようとする 2 つのスレッド tA と tB もあります。
instanceMethod のロック: tA が testA の instanceMethod のロックを取得すると、tBはtestAの同じメソッドにアクセスできませんが、tBはtestBのinstanceMethodを自由に呼び出すことができます。instanceMethodに対する同期はインスタンス レベルのロックであるため
staticMethod でのロック: ただし、tA がstaticMethodでロックを取得すると、静的メソッドでの同期はクラス レベルの lock であるため、ロックは testA または testB とは関係ありません。つまり、tA がロックを解除するまで、tB はstaticMethodにまったくアクセスできません。
実際には、 class の static メソッドのロックはFoo
、ロックをかけるのと同じFoo.class
です (これが唯一のインスタンスです)。
public static void doSomething()
{
synchronized(Foo.class)
{
// ...
}
}
あなたが正しく、記事が少し慎重すぎることを示す私のテストコードは次のとおりです。
class Y {
static synchronized void staticSleep() {
System.out.println("Start static sleep");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("End static sleep");
}
synchronized void instanceSleep() {
System.out.println("Start instance sleep");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
System.out.println("End instance sleep");
}
}
public class X {
public static void main(String[] args) {
for (int i = 0; i < 2; ++i) {
new Thread(new Runnable() {
public void run() {
Y.staticSleep();
}
}).start();
}
for (int i = 0; i < 10; ++i) {
new Thread(new Runnable() {
public void run() {
new Y().instanceSleep();
}
}).start();
}
}
}
版画:
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start static sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End static sleep
Start static sleep
End static sleep
したがって、インスタンスのメソッドにはstatic synchronized
関係ありません...synchronized
もちろん、static synchronised
メソッドがシステム全体で使用されている場合は、それらがマルチスレッド システムのスループットに最も影響を与えることが期待できるため、危険を冒して使用してください...
あなたの言うとおりです — 実際のロックはClass
インスタンス自体にあり、クラスのどのインスタンスにもありません (すべてのインスタンスは言うまでもなく) — しかし、リンクされたページを文字通りに解釈しすぎていると思います。それ自体が「静的ロック (クラス ロック)」というフレーズを使用しているため、作成者はロックがどのように機能するかを明確に認識しています。ただし、同期された静的メソッドをすべて使用している異なるスレッドに多数のインスタンスがある場合、それらのインスタンスはすべて互いにロックアウトされます。同期された静的メソッドによって同期されたインスタンスメソッドがブロックされることはありませんが、それでも問題は存在します。
「クラスのすべてのインスタンスをロックする」とは言いません。「クラスのすべてのインスタンスをロックします。それは言葉遣いが悪く、確かに間違っていますが、あなたが言ったことを言っているわけではありません。