0

重複の可能性:
同期と静的同期の違いは何ですか?

クラスロックに対するオブジェクトロックの利点は何ですか?

例えば、

 public static void log2(String msg1, String msg2){
       synchronized(MyClass.class){
          log.writeln(msg1);
          log.writeln(msg2);  
       }
    }

と、

public void log2(String msg1, String msg2){
       synchronized(this){
          log.writeln(msg1);
          log.writeln(msg2);
       }
    }
4

3 に答える 3

1

クラスにロックを作成すると、クラスのすべてのインスタンスがロックを共有します。インスタンスが 1 つの場合、違いはありません。何千ものインスタンスがある場合、それらはすべてまったく同じロックを使用します。多くのスレッドが同時にロックを取得しようとすると、相互にブロックされます。最悪の場合、これによりコードがまったくスレッドが存在しないかのように動作する可能性があります。

インスタンスにロックを作成すると、複数のスレッドが異なるインスタンスで動作する限り、保護されたコードを実行できます。ここでは、スレッドは互いにブロックしません。したがって、このアプローチのパフォーマンスは向上します。

しかし、それはあなたが尋ねる必要があるものではありません。本当の問題は、どのようなロックが必要かということです。

1 つのスレッドだけがログに書き込めるようにする場合は、 で同期する必要がありますlog。このアプローチには、複数のログ ファイル (たとえば、スレッドごとに 1 つ) を使用し始めると、自動的に正しく機能するという追加の利点があります。

于 2012-10-15T12:05:47.380 に答える
0

それらは異なるオブジェクトをロックするため、相互に変更することはできません。

オブジェクトのロックが適切な場合は、それを使用します。クラスをロックしたい場合 (これはありそうもないことですが)、それを使用します。

この組み合わせを検討します。

public void log2(String msg1, String msg2){
    synchronized(this) {
        synchronized(log) {
            log.writeln(msg1);
            log.writeln(msg2);
        }
    }
}

これにより、オブジェクトが変更されていないことが保証され、行がログに一緒に表示されます。

ただし、log2 は変更可能なフィールドを使用していないように見えるため、使用できます

private final Log log = ...

public void log2(String msg1, String msg2){
    synchronized(log) {
        log.writeln(msg1);
        log.writeln(msg2);
    }
}
于 2012-10-15T11:48:03.207 に答える
0

以下に示す Logger クラスから、Log クラスが Lock オブジェクトを使用するように変更された場合、log(String msg1, String msg2) を呼び出すスレッドは、新しい同期ポリシーを使用してスレッドセーフなログに対して操作を実行します。しかし、log(String msg1) メソッドを呼び出すスレッドは常に Log インスタンスで同期し、Log クラス内のすべての Lock オブジェクトが一度に保持されます。このような状態では、Logger の実装が壊れてしまいます。そのため、クライアント側のロックではなく、プライベートの最終的な Lock オブジェクトまたは Lock クラスを使用することをお勧めします。

public class Logger {
    private final Log log;
    private final Object lock = new Object();

    public Logger(Log log) {
        this.log = log;
    }

    public void log(String msg1) {            // log synchronizes on log instance
        synchronized (log) {        
            log.writeln(msg1);      
        }
    }

    public void log(String msg1, String msg2) {   // log uses private final lock
        synchronized (lock) {
            log.writeln(msg1);
                        log.writeln(msg2);  
        }
    }   
}
于 2012-10-16T02:33:27.680 に答える