ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • synchronized 동기화
    자바 및 spring boot 2024. 6. 2. 16:01

    `synchronized`는 Java에서 멀티스레딩 환경에서 동기화(synchronization)를 위해 사용하는 키워드입니다. 이는 특정 코드 블록이나 메서드가 한 번에 하나의 스레드만 접근할 수 있도록 제한하여, 여러 스레드가 동시에 접근할 때 발생할 수 있는 데이터 불일치 문제를 방지합니다.

    ### 기본 사용법

    `synchronized`는 주로 두 가지 방식으로 사용됩니다: 블록 수준 동기화와 메서드 수준 동기화입니다.

    1. **블록 수준 동기화**:
       특정 객체를 대상으로 동기화 블록을 정의합니다. 이 경우 해당 블록 내의 코드가 실행될 때, 지정된 객체에 대한 잠금을 획득한 스레드만 접근할 수 있습니다.

       ```java
       public class Counter {
           private int count = 0;
           private final Object lock = new Object();

           public void increment() {
               synchronized (lock) {
                   count++;
               }
           }

           public int getCount() {
               synchronized (lock) {
                   return count;
               }
           }
       }
       ```

    2. **메서드 수준 동기화**:
       메서드 자체에 `synchronized` 키워드를 붙여서 해당 메서드가 호출될 때 객체에 대한 잠금을 획득하도록 합니다.

       ```java
       public class Counter {
           private int count = 0;

           public synchronized void increment() {
               count++;
           }

           public synchronized int getCount() {
               return count;
           }
       }
       ```

    ### 동작 원리

    `synchronized` 키워드를 사용하면 다음과 같은 방식으로 동작합니다:

    1. **잠금 획득**:
       스레드가 `synchronized` 블록이나 메서드에 들어가면, 해당 객체의 잠금을 획득합니다. 다른 스레드가 동일한 객체의 `synchronized` 블록이나 메서드에 접근하려고 하면, 잠금이 해제될 때까지 대기합니다.

    2. **코드 실행**:
       잠금을 획득한 스레드는 `synchronized` 블록이나 메서드 내부의 코드를 실행합니다.

    3. **잠금 해제**:
       블록이나 메서드 실행이 끝나면 잠금을 해제하여 다른 대기 중인 스레드가 접근할 수 있도록 합니다.

    ### 주의사항

    - **성능 저하**: 동기화는 멀티스레딩 환경에서 데이터 불일치 문제를 해결하는데 유용하지만, 잠금을 획득하고 해제하는 오버헤드가 있기 때문에 성능 저하를 초래할 수 있습니다.
    - **데드락(교착 상태)**: 두 개 이상의 스레드가 서로 상대방의 잠금을 기다리며 무한 대기 상태에 빠지는 데드락 상황을 주의해야 합니다.
    - **필요한 경우에만 사용**: 동기화가 필요한 최소한의 코드 블록에만 `synchronized`를 적용하여 성능에 미치는 영향을 최소화해야 합니다.

    ### 예제

    다음은 `synchronized`를 사용하여 두 개의 스레드가 안전하게 카운터 값을 증가시키는 예제입니다.

    ```java
    public class SynchronizedExample {
        public static void main(String[] args) throws InterruptedException {
            Counter counter = new Counter();

            Runnable task = () -> {
                for (int i = 0; i < 1000; i++) {
                    counter.increment();
                }
            };

            Thread thread1 = new Thread(task);
            Thread thread2 = new Thread(task);

            thread1.start();
            thread2.start();

            thread1.join();
            thread2.join();

            System.out.println("Final count: " + counter.getCount());
        }
    }

    class Counter {
        private int count = 0;

        public synchronized void increment() {
            count++;
        }

        public synchronized int getCount() {
            return count;
        }
    }
    ```

    이 예제에서는 두 개의 스레드가 `Counter` 객체의 `increment` 메서드를 동시에 호출하더라도, `synchronized` 키워드 덕분에 `count` 변수가 안전하게 증가합니다.

Designed by Tistory.