非静的メソッドを変更する同期キーワードと静的メソッドを変更することの違いは何ですか?

リファレンス:Javaクラスとオブジェクトロックロックの包括的な分析
リファレンス:同期された同期静的メソッドと非静的メソッドの概要
リファレンスブック:「Javaマルチスレッドプログラミングコアテクノロジー」作成者:High Hongyan

残念ながら、大規模なオープンソースフレームワークで使用されていても、同期変更静的メソッドの実用的なアプリケーションを見つけることができませんでした。直接の結論:

  • 非静的メソッドの同期変更は、実際には、メソッドを呼び出すオブジェクトをロックします。これは、一般に「オブジェクトロック」として知られています。
  • 静的メソッドの同期変更は、実際にはこのタイプのオブジェクトをロックします。これは一般に「クラスロック」として知られています。

同期された変更された静的メソッドの状況に関して、コード例を直接見てみましょう。

public class Run {
    public static void main(String[] args) {
        ThreadA a = new ThreadA();
        a.setName("A");
        a.start();

        ThreadB b = new ThreadB();
        b.setName("B");
        b.start();
    }
}

class Service {
   synchronized public static void printA() {
        try {
            System.out.println("线程名称为:" + Thread.currentThread().getName()
                    + "在" + System.currentTimeMillis() + "进入printA");
            Thread.sleep(3000);
            System.out.println("线程名称为:" + Thread.currentThread().getName()
                    + "在" + System.currentTimeMillis() + "离开printA");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    synchronized public static void printB() {
        System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
                + System.currentTimeMillis() + "进入printB");
        System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
                + System.currentTimeMillis() + "离开printB");
    }
}

class ThreadA extends Thread {
    @Override
    public void run() {
        Service.printA();
    }

}


class ThreadB extends Thread {
    @Override
    public void run() {
        Service.printB();
    }
}

演算結果:

线程名称为:A在1466149372909进入printA
线程名称为:A在1466149375920离开printA
线程名称为:B在1466149375920进入printB
线程名称为:B在1466149375920离开printB

2つのスレッドが同じクラスロックをめぐって競合しているため、同期されます

  • 同期(クラス)

上記のサービスクラスコードを次のように変更します。

class Service {

    public static void printA() {
        synchronized (Service.class) {
            try {
                System.out.println("线程名称为:" + Thread.currentThread().getName()
                        + "在" + System.currentTimeMillis() + "进入printA");
                Thread.sleep(3000);
                System.out.println("线程名称为:" + Thread.currentThread().getName()
                        + "在" + System.currentTimeMillis() + "离开printA");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public static void printB() {
        synchronized (Service.class) {
            System.out.println("线程名称为:" + Thread.currentThread().getName()
                    + "在" + System.currentTimeMillis() + "进入printB");
            System.out.println("线程名称为:" + Thread.currentThread().getName()
                    + "在" + System.currentTimeMillis() + "离开printB");
        }
    }
}

演算結果:

线程名称为:A在1466149372909进入printA
线程名称为:A在1466149375920离开printA
线程名称为:B在1466149375920进入printB
线程名称为:B在1466149375920离开printB

2つのスレッドはまだ同じクラスロックをめぐって競合しているため、同期されます

質問:キーワードsynchronizedは静的メソッドを変更します。まれです。どこで使用されますか?

おすすめ

転載: blog.csdn.net/zhangjin1120/article/details/110246656