자바 동기화(synchronized) 예제

Minjae An·2023년 9월 11일
0

Java

목록 보기
1/2

예제1

public class Printer {
    public Printer() {
    }

    public synchronized void print1() {
            for (int i = 0; i < 3; i++) {
                System.out.print(i);
            }
    }

    public synchronized void print2() {
        for (int i = 3; i < 6; i++) {
               System.out.print(i);
         }
    }

    public static void main(String[] args) {
        Printer printer = new Printer();

        new Thread(() -> {
            printer.print1();
        }).start();

        new Thread(() -> {
            printer.print2();
        }).start();
    }
}

각 메서드에 개별적으로 synchronized 처리가 되어있다. 한 메서드가 독점적으로
락을 점유하므로 012345 혹은 345012와 같이 순차적으로 실행된다.

예제2

public class Printer {
    public Printer() {
    }

    public synchronized void print1() {
            for (int i = 0; i < 3; i++) {
                System.out.print(i);
            }
    }

    public  void print2() {
        for (int i = 3; i < 6; i++) {
               System.out.print(i);
         }
    }

    public static void main(String[] args) {
        Printer printer = new Printer();

        new Thread(() -> {
            printer.print1();
        }).start();

        new Thread(() -> {
            printer.print2();
        }).start();
    }
}

print1 메서드에는 synchronized 처리가 되어있지만 print2 에는
동기화 처리가 되어있지 않다. 따라서 print1의 실행중 print2의 개입이
가능하므로 340125, 012345, 345012, 304152와 같은 실행 형태가 가능하다.

예제3

public class Printer {
    public Printer() {
    }

    public void print1() {
        synchronized (this) {
            for (int i = 0; i < 3; i++)
                System.out.print(i);
        }
    }

    public synchronized void print2() {
        for (int i = 3; i < 6; i++) 
            System.out.print(i);
      
    }

    

    public static void main(String[] args) {
        Printer printer = new Printer();

        new Thread(() -> {
                printer.print1();
        }).start();

        new Thread(() -> {
                printer.print2();
        }).start();
    }
}

print1에서는 synchronized(this)를 통해 인스턴스에 대한 락을 점유하고
있다. 따라서, print1->print2 혹은 print2->print1의 실행 순서가 가능하여
012345, 345012와 같은 형태가 도출된다.

예제4

public class Printer {
    public Printer() {
    }

    public void print1() {
        synchronized (obj1) {
            for (int i = 0; i < 3; i++)
                System.out.print(i);
        }
    }

    public synchronized void print2() {
        for (int i = 3; i < 6; i++) 
            System.out.print(i);
      
    }

    private final Object obj1 = new Object();

    public static void main(String[] args) {
        Printer printer = new Printer();

        new Thread(() -> {
                printer.print1();
        }).start();

        new Thread(() -> {
                printer.print2();
        }).start();
    }
}

print1에서는 실행되는 메서드들과 상관 없는 obj1에 락을 걸고 있다.
따라서 print1print2과 뒤섞여 실행되는 형태가 도출된다.
340125, 012345, 345012, 304152

예제5

public class Printer {
    public Printer() {
    }

    public synchronized static void print1() {
            for (int i = 0; i < 3; i++)
                System.out.print(i);
    }

    public synchronized void print2() {
        for (int i = 3; i < 6; i++) 
            System.out.print(i);
      
    }

    public static void main(String[] args) {
        Printer printer = new Printer();

        new Thread(() -> {
                Printer.print1();
        }).start();

        new Thread(() -> {
                printer.print2();
        }).start();
    }
}

print1static 메서드이고 synchronized로 락이 클래스 단위에 걸리게
된다. 따라서 print1print2의 실행이 뒤섞여 나타날 수 있다.

예제6

public class Printer {
    public Printer() {
    }

    public static void print1() {
        synchronized (Printer.class) {
            for (int i = 0; i < 3; i++) {
                System.out.print(i);
            }
        }
    }

    public synchronized static void print2() {
        for (int i =3; i < 6; i++) {
            System.out.print(i);
        }
    }


    public static void main(String[] args) {
        new Thread(() -> {
            Printer.print1();
        }).start();

        new Thread(() -> {
            Printer.print2();
        }).start();
    }
}

print1은 클래스에 락을 걸고 있고, print2static 메서드이며
synchronized 처리시 역시 클래스 단위로 락을 걸게 된다. 따라서 순차적인
실행 형태인 012345 혹은 345012 가 가능하다.

profile
도전을 성과로

0개의 댓글