Java 동기화 문제 8가지

문제 1: 다음 코드에서 전화를 걸기 전에 메시지를 먼저 보낼까요? 메시지 전송

public class A {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();

        // 락 적용
        new Thread(()->{
            try {
                phone.sendMessage();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"ThreadA").start();
        // 1초 대기
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{ phone.makeCall(); },"ThreadB").start();

    }
}
@SuppressWarnings("all")
class Phone {

    // synchronized는 메서드 호출자에 대한 락
    // 두 메서드는 동일한 락 사용, 먼저 획득한 스레드가 실행
    public  synchronized void sendMessage() throws InterruptedException {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("메시지 전송");
    }
    public synchronized void makeCall() {
        System.out.println("전화 걸기");
    }

}

문제 2---두 개의 객체로 변경했을 때, 전화를 걸기 전에 메시지를 먼저 보낼까요? 전화 걸기

public class A {
    public static void main(String[] args) throws InterruptedException {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();
        

        // 락 적용
        new Thread(()->{
            try {
                phone1.sendMessage();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"ThreadA").start();
        // 1초 대기
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{ phone2.makeCall(); },"ThreadB").start();

    }
}
@SuppressWarnings("all")
class Phone {

    // synchronized는 메서드 호출자에 대한 락
    // 두 메서드는 동일한 락 사용, 먼저 획득한 스레드가 실행
    public  synchronized void sendMessage() throws InterruptedException {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("메시지 전송");
    }
    public synchronized void makeCall() {
        System.out.println("전화 걸기");
    }

}

문제 3---일반 메서드 추가 시, 메시지 전송 후에 hello가 출력될까요?

public class B {
    public static void main(String[] args) throws InterruptedException {
        Phone2 phone = new Phone2();

        new Thread(()->{
            try {
                phone.sendMessage();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"ThreadA").start();
        // 1초 대기
         TimeUnit.SECONDS.sleep(1);

        new Thread(()->{ phone.hello(); },"ThreadB").start();

    }
}
@SuppressWarnings("all")
class Phone2 {

    // synchronized는 메서드 호출자에 대한 락
    // 두 메서드는 동일한 락 사용, 먼저 획득한 스레드가 실행
    public  synchronized void sendMessage() throws InterruptedException {

        TimeUnit.SECONDS.sleep(4);
        System.out.println("메시지 전송");
    }
    public synchronized void makeCall() {
        System.out.println("전화 걸기");
    }
    // 락이 없음, 동기화 메서드가 아님
    public  void hello() {
        System.out.println("hello");
    }

}

문제 4---다른 객체로 메시지 전송과 hello 메서드 호출 시 결과는?

public class B {
    public static void main(String[] args) throws InterruptedException {
        Phone2 phone1 = new Phone2();
        Phone2 phone2 = new Phone2();

        new Thread(()->{
            try {
                phone1.sendMessage();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"ThreadA").start();
        // 1초 대기
         TimeUnit.SECONDS.sleep(1);

        new Thread(()->{ phone2.hello(); },"ThreadB").start();

    }
}
@SuppressWarnings("all")
class Phone2 {

    public  synchronized void sendMessage() throws InterruptedException {

        TimeUnit.SECONDS.sleep(4);
        System.out.println("메시지 전송");
    }
    public synchronized void makeCall() {
        System.out.println("전화 걸기");
    }
    // 락이 없음, 동기화 메서드가 아님
    public  void hello() {
        System.out.println("hello");
    }

}

설명은 동일합니다

문제5---static 키워드 추가 시 실행 결과는?

public class C {
    public static void main(String[] args) throws InterruptedException {
        Phone3 phone = new Phone3();
        new Thread(()->{
            try {
                phone.sendMessage();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"ThreadA").start();
        // 1초 대기
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{ phone.makeCall(); },"ThreadB").start();

    }
}
@SuppressWarnings("all")
// Phone3은 유일한 클래스 객체 Phone3.class(전역 유일)
class Phone3 {

    // synchronized는 메서드 호출자에 대한 락
    // 두 메서드는 동일한 락 사용, 먼저 획득한 스레드가 실행
    // static 메서드는 클래스 로딩 시 생성, 클래스 템플릿
    // 이 경우 락은 클래스 객체
    public  static synchronized void sendMessage() throws InterruptedException {

        TimeUnit.SECONDS.sleep(4);
        System.out.println("메시지 전송");
    }
    public static synchronized void makeCall() {
        System.out.println("전화 걸기");
    }
}

문제6---static 키워드로 수정한 후 두 개의 다른 객체로 호출 시 결과는?

public class C {
    public static void main(String[] args) throws InterruptedException {
        // 두 객체지만, 현재 락은 클래스 객체
        // 두 객체의 클래스 템플릿은 하나만 존재
        Phone3 phone1 = new Phone3();
        Phone3 phone2 = new Phone3();


        new Thread(()->{
            try {
                phone1.sendMessage();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"ThreadA").start();
        // 1초 대기
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{ phone2.makeCall(); },"ThreadB").start();

    }
}
@SuppressWarnings("all")
// Phone3은 유일한 클래스 객체 Phone3.class(전역 유일)
class Phone3 {

    // synchronized는 메서드 호출자에 대한 락
    // 두 메서드는 동일한 락 사용, 먼저 획득한 스레드가 실행
    // static 메서드는 클래스 로딩 시 생성, 클래스 템플릿
    // 이 경우 락은 클래스 객체
    public  static synchronized void sendMessage() throws InterruptedException {

        TimeUnit.SECONDS.sleep(4);
        System.out.println("메시지 전송");
    }
    public static synchronized void makeCall() {
        System.out.println("전화 걸기");
    }
}

문제7--일반 동기화 메서드와 정적 동기화 메서드 함께 사용 시 실행 순서는?

public class D {
    public static void main(String[] args) throws InterruptedException {

        Phone4 phone = new Phone4();

        new Thread(()->{
            try {
                phone.sendMessage();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"ThreadA").start();
        // 1초 대기
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{ phone.makeCall(); },"ThreadB").start();

    }
}
@SuppressWarnings("all")
// Phone4은 유일한 클래스 객체 Phone4.class(전역 유일)
class Phone4 {


    // 정적 동기화 메서드
    public  static synchronized void sendMessage() throws InterruptedException {

        TimeUnit.SECONDS.sleep(4);
        System.out.println("메시지 전송");
    }
    // 일반 동기화 메서드
    public  synchronized void makeCall() {
        System.out.println("전화 걸기");
    }


}

분석:

문제8: 두 개의 다른 객체로 호출 시 결과는?

public class D {
    public static void main(String[] args) throws InterruptedException {

        Phone4 phone1 = new Phone4();
        Phone4 phone2 = new Phone4();

        new Thread(()->{
            try {
                phone1.sendMessage();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"ThreadA").start();
        // 1초 대기
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{ phone2.makeCall(); },"ThreadB").start();

    }
}
@SuppressWarnings("all")
// Phone4은 유일한 클래스 객체 Phone4.class(전역 유일)
class Phone4 {


    // 정적 동기화 메서드
    public  static synchronized void sendMessage() throws InterruptedException {

        TimeUnit.SECONDS.sleep(4);
        System.out.println("메시지 전송");
    }
    // 일반 동기화 메서드
    public  synchronized void makeCall() {
        System.out.println("전화 걸기");
    }


}

결과:

태그: Java 멀티스레드 동기화 메서드 락 기능 정적 동기화 스레드 동기화

8월 9일 21:25에 게시됨