synchronized異なる位置を修飾する役割


synchronized異なる位置を修飾する役割
例1:複数の方法を修飾する
public class SynchronizedTest {
    
    public static void main(String[] args) {
        Hello hello = new Hello();
        new Thread(hello::printA, "  A").start();
        new Thread(hello::printB, "  B").start();
    }

    static class Hello {
        synchronized void printA() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        synchronized void printB() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

実行結果:すべてスレッドAが実行されています.
  A     
  A     
  A     
  A     
  A     
  A     
  A     
  A     
  A     
  A     
...

例2:複数のコードブロックを修飾する
public class SynchronizedTest {

    public static void main(String[] args) {
        Hello hello = new Hello();
        new Thread(hello::printA, "  A").start();
        new Thread(hello::printB, "  B").start();
    }

    static class Hello {
        void printA() {
            synchronized (this) {
                for (; ; ) {
                    System.out.println(Thread.currentThread().getName() + "     ");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        synchronized void printB() {
            synchronized (this) {
                for (; ; ) {
                    System.out.println(Thread.currentThread().getName() + "     ");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

実行結果:すべてスレッドAが実行されています.
  A     
  A     
  A     
  A     
  A     
  A     
  A     
  A     
  A     
  A     
...

例3:一つの方法を修飾し、もう一つの方法を修飾しない
public class SynchronizedTest {

    public static void main(String[] args) {
        Hello hello = new Hello();
        new Thread(hello::printA, "  A").start();
        new Thread(hello::printB, "  B").start();
    }

    static class Hello {
        void printA() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        synchronized void printB() {
            synchronized (this) {
                for (; ; ) {
                    System.out.println(Thread.currentThread().getName() + "     ");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

実行結果:AとBの2つのスレッドが交互に実行されます.
  A     
  B     
  A     
  B     
  A     
  B     
  A     
  B     
  A     
  B     
  A     
  B     
...

例4:オブジェクトを修飾し、オブジェクト内のメソッドをロックする必要はありません(synchronized修飾はありません)
public class SynchronizedTest {

    public static void main(String[] args) {
        Hello hello = new Hello();
        synchronized (hello) {
            new Thread(hello::printA).start();
        }
        synchronized (hello) {
            new Thread(hello::printB).start();
        }
    }

    static class Hello {
        void printA() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        void printB() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

出力、スレッドが交互に実行
  A     
  B     
  A     
  B     
  A     
  B     
  B     
  A     
  A     
  B     
  A     

例5:オブジェクトを修飾する方法synchronized修飾があり、オブジェクトがない
public class SynchronizedTest {

    public static void main(String[] args) {
        Hello hello = new Hello();
        synchronized (hello) {
            new Thread(hello::printA, "  A").start();
        }
        synchronized (hello) {
            new Thread(hello::printB, "  B").start();
        }
    }

    static class Hello {
        synchronized void printA() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        void printB() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

実行結果:
  A     
  B     
  A     
  B     
  A     
  B     
  A     
  B     
  A     

例6:オブジェクトを修飾し、オブジェクトのメソッドをsynchronizedで修飾する
public class SynchronizedTest {

    public static void main(String[] args) {
        Hello hello = new Hello();
        synchronized (hello) {
            new Thread(hello::printA, "  A").start();
        }
        synchronized (hello) {
            new Thread(hello::printB, "  B").start();
        }
    }

    static class Hello {
        synchronized void printA() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        synchronized void printB() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

実行結果:
  A     
  A     
  A     
  A     
  A     
  A     
  A     
  A     
  A     

例7:修飾クラス
public class SynchronizedTest {

    public static void main(String[] args) {
        Hello hello = new Hello();
        synchronized (Hello.class) {
            new Thread(hello::printA, "  A").start();
            new Thread(hello::printA, "  B").start();
        }
    }

    static class Hello {
        void printA() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

         void printB() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

出力:
  A     
  B     
  B     
  A     
  A     
  B     
  A     
  B     

例8:クラス内の静的メソッドを修飾し、synchronized修飾を同時に実行する静的およびメソッドと修飾されていない静的メソッド
public class SynchronizedTest {

    public static void main(String[] args) {
        new Thread(Hello::printA, "  A").start();
        new Thread(Hello::printB, "  B").start();
    }

    static class Hello {
        synchronized static void printA() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        static void printB() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

出力:
  A     
  B     
  A     
  B     
  A     
  B     
  A     
  B     

例9:クラス内の静的メソッドを修飾し、synchronized修飾を同時に実行する静的メソッドとメソッド
public class SynchronizedTest {

    public static void main(String[] args) {
        new Thread(Hello::printA, "  A").start();
        new Thread(Hello::printB, "  B").start();
    }

    static class Hello {
        synchronized static void printA() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        synchronized static void printB() {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + "     ");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

出力:
  A     
  A     
  A     
  A     
  A     
  A     

まとめてみます.
  • synchronizedは、静的メソッド、非静的メソッド、コードブロック、オブジェクト、クラスを修飾することができる.
  • 修飾が誰であるかにかかわらず、ロックされているのはsynchronizedキーワードの後ろの括弧で囲まれた部分です.この部分はマルチスレッドで同時にアクセスできません.
  • は、オブジェクトまたはクラスを修飾しても、複数のスレッドが実行される場合、異なる場合にオブジェクトまたはクラスのsynchronized修飾の部分に実行される限り、実行することができる.すなわち,synchronized修飾のコードブロックと修飾されていないコードブロックとを同時にオブジェクトやクラスにロックをかけることができる.