본문 바로가기

Web Sever 개발과 CS 기초/자바

Concurrent List, Concurrent HashMap 쉽게 이해하기

개요 목적

멀티 thread를 사용 시 동시성 문제를 주의해야 한다.

동시성 문제를 해결하기 위한 다양한 방법들이 있다. (동기화, ThreadLocal, Atomic 등)

이번에는 많은 자료를 저장하는 list와 hash가 공통 자원일 때,

동시성 문제를 해결해주는 CucurrentLIstConcurrentHash에 대해 알아보자.

Concurrent List

<일반 리스트를 사용할 때 생기는 문제>

import java.util.ArrayList;

public class ConcurrentLIst {
    public static void main(String[] args) throws InterruptedException {
        TestList testList = new TestList();
        Thread t1 = new Thread(testList);
        Thread t2 = new Thread(testList);
        Thread t3 = new Thread(testList);
        Thread t4 = new Thread(testList);

        t1.start();
        t2.start();
        t3.start();
        t4.start();

        t1.join();
        t2.join();
        t3.join();
        t4.join();
    }
}

class TestList implements Runnable {
    ArrayList<Integer> list1 = new ArrayList();
    
    @Override
    public void run() {
        for (int i = 0; i < 500; i++) {
            int addNum = (int) (Math.random() * 10);
            list1.add(addNum);
            System.out.println("+" + addNum);
            System.out.println(list1);
            int removeNum = list1.remove(0);
            System.out.println("-" + removeNum);
            System.out.println(list1);

        }
    }
}

<결과>

+3
+6
[6, 3]
+6
[3]
[6, 3]
-3
[]
-6
[1]
java.lang.IndexOutOfBoundsException

여러 스레드에서 리스트 안의 값을 동시에 빼가서,

리스트가 비어 버리는 상황 발생했다. 제거할 값이 없어 나타나는 예외도 발생했다.

 

<CopyOnWriteArrayList 사용>

//    ArrayList<Integer> list = new ArrayList();
->
CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();

<CopyOnWriteArrayList 사용 결과>

+2
[2]
-2
[]
+9
[9]
-9
[]

Process finished with exit code 0

리스트 접근 동작들이 모두 순차적으로 일어난다.

ConcurrentHashMap

ConcurrentHashMap도 CopyOnWriteArrayList처럼, 동시성 문제를 해결한다.

다른 해시맵 자료 구조와의 차이를 한번 알아보자.

  • HashMap

주요 메소드에 synchronized키워드가 없어서 동시성 문제를 해결하지 못한다.

HashTable과 다르게 key,value에 null값을 입력할 수 있다.

  • HashTable

주요 메소드에 synchronized 키워드 있다. null값을 허용하지 않는다.

  • ConcurrentHashMap

HashTable과 기능은 같다. .

HashTable과 달리, 값을 넣을 때 무조건 동기화를 진행하지 않는다.

같은 노드 값이 들어왔을 때만 동기화를 진행해서, 멀티스레드 환경에서 성능을 높인다.


Reference

https://taes-k.github.io/2021/12/27/mac-terminal/

https://goneoneill.tistory.com/47

https://tomining.tistory.com/169