Home 동시성 문제를 제어하는 방법
Post
Cancel

동시성 문제를 제어하는 방법

동시성 문제를 제어하는 방법

📌 정의

멀티 스레드 환경에서 여러 스레드가 동시에 하나의 자원을 공유할 때 동시성 문제, 데드락 등 여러 문제가 발생한다. 해당 문제 중 동시성 문제를 제어하는 방법을 알아보자.

1️⃣ 암시적 잠금

하나의 스레드가 해당 메소드를 실행하고 있을 때 다른 스레드가 해당 메소드를 실행하지 못하고 대기하게 하는 방법. 잠금은 메소드, 변수에 각 각 걸 수 있다.

😎 예제
1
2
3
4
5
6
7
class Count {
    private int count;
    
    public synchronized int view() {
        return count++;
    }
}

위의 예제는 메소드 잠금이다.

1
2
3
4
5
6
7
8
class Count {
    private Integer count;
    public int view() {
        synchronized (this.count) {
            return count++;
        }
    }
}

2️⃣ 명시적 잠금

synchronized 키워드 없이 명시적으로 ReentrantLock을 사용하는 잠금.

운영체제에서 임계영역과 비슷한 느낌이다.

😎 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class CountingTest {
    public static void main(string[] args) {
        Count count = new Count();
        for (int i = 0; i < 100; i++) {
            new Thread() {
                public void run() {
                    for(int j = 0; j < 1000; j++) {
                        count.getLock().lock();
                        System.out.println(count.view());
                        count.getLock().unlock();
                    }
                }
            }.start();
        }
    }
}

class Count {
    private int count = 0;
    private Lock lock = new ReentrantLock();
    public int view() {
        return count++;
    }
    public Lock getLock() {
        return lock;
    }
}

3️⃣ volatile

스레드들이 자원에 read, write를 진행할 때 항상 메모리에 접근하지 않는다. 성능의 향상을 위해 CPU 캐스에 값을 저장하기 때문에 해당 값이 메모리에 저장된 실제 값고 항상 일치하는지 보장할 수 없다.

메인 메모리에 저장된 실제 자원의 값을 볼 수 있는 개념을 자원의 가시성이라고 부른다.

volatile은 위와 같은 CPU 캐시 사용을 막는다. 변수에 volatile 키워드를 붙여주면 해당 변수는 캐시에 저장되는 대상에서 제외된다. 캐시 사용으로 인한 테이터 불일치를 막는다.

4️⃣ Concurrent

Atomic~~와 같은 클래스는 단순한 증감연산을 메소드로 제공해준다. 해당 클래스의 메소드는 내부적으로 Thread-safe하게 구조화되어 있다.

Concurrent~~와 같은 컬랙션들은 락을 사용할 때 발생하는 성능 저하를 최소한으로 만들어두었다.

This post is licensed under CC BY 4.0 by the author.