억대 연봉을 위한 인간수업
반응형

java는 멀티 스레드를 지원하는 언어이다. 그러다 보니 싱글 스레드에서 최적화된 접근이 있고, 멀티 스레드에서 사용하기 위한 방법도 존재한다. 여기서 멀티 스레드 환경에서 어떤 함수나 변수, 객체가 여러 스레드로부터 동시에 접근이 일어나도 프로그램 실행에 문제가 없는 Thread-safe를 고려한 자료형이 존재한다. 

 

ConcurrentHashMap이란?

  • 멀티 스레드 환경에서도 사용할 수 있게 나온 클래스로, 동시성을 높이기 위해 나온 클래스
  • hashTable과 synchronized map 보다 더 나은 성능을 가지고 있다
  • 왜냐면 concurrentHash Map 은 map의 일부에만 lock을 걸고, hashTable과 Synchronized는 map 전체에 lock을 걸기 때문

 

사용 예시 1

public class ConcurrentHashMapTest {
	//map 선언 후 new ConcurrentHashMap으로 객체 생성
	private TestMap <Integer, String> map = new ConcurrentHashMap<Integer, String>();
    
	public void test() {
		map.put(1, "apple");
		map.put(2, "abocado");

		for(TestMap.Entry<Integer, String> entry : map.entrySet()) {
			String key = entry.getKey();
			String value = entry.getValue();
		}
	}
}

 

사용 예시 2

import java.util.concurrent.ConcurrentHashMap;
import java.util.Iterator;
import java.util.Set;

public class ConcurrentHashMapTest {

	private TestMap <Integer, String> map = new ConcurrentHashMap<Integer, String>();
    
	public void test() {
		map.put(1, "google");
		map.put(2, "apple");

		Set<TestMap.Entry<String, String>> entry = map.entrySet();
		Iterator<TestMap.Entry<String, String>> it = entry.iterator();
		while(it.hasNex()) {
			TestMap.Entry<String, String>> data = it.next();
			String key = data.getKey();
			String value = data.getValue();
		}
	}
}

 

한계점

  • 추가 및 삭제 같은 수정 작업만 동기화된다.
  • key와 value의 Null 값이 허용되지 않는다.
  • 데이터 추가, 삭제가 hashmap보다 느리다.
    • 그래서 concurrent hash map은 내부적으로 동기화한 멀티 스레드에 적합하고, hashmap은 단일 스레드에 적합

 

잘못된 사용 방법

class SharedData {
    private Integer intData = 0;
    private Boolean boolData = false;

    public int getInt() { synchronized (intData) { return intData; } }
    public void setInt(int n) { synchronized (intData) { intData = n; } }
    public boolean getBool() { synchronized (boolData) { return boolData; } }
    public void setBool(boolean b) { synchronized (boolData) { boolData = b; } }
}

 

  • setInt()나 setBool() 함수가 호출될 때마다 lock으로 사용되는 intData, boolData 객체가 변할 수 있는데 이런 경우 스레드들이 서로 다른 lock에 접근하게 된다.
  • 그래서 setter메소드가 다른 값이 할당되는 순간, lock 객체가 동기화 블럭 내에 다른 객체로 변경됐기 때문에 실제 객체가 바뀌어 스레드 간의 동기화가 깨지게 된다.
  • 따라서 어떤 경우라도 synchronized 블럭 내에서 lock 객체의 참조 값을 변경하면 안 된다.
  • Auto boxing 이 발생하는 Integer, Boolean, Long 등과 같은 클래스를 사용할 때 잘못 사용할 수가 있다.
  • 결론적으로 값 객체를 직접 lock으로 사용하지 말아야 한다.

 

출저 : https://roynus.tistory.com/672

 

 


 

concurrent List란?

  • 멀티 스레드 환경에서 사용할 수 있는 리스트 자료형
  • 내부 배열은 수정되지 않으니, 데이터를 찾을 때 내부에서 lock이 필요하지 않아 속도가 매우 빠르다는 장점
  • 데이터를 전달할 때 현재 상태를 스냅샷으로 가지고 다니는 방식

 

사용 방법

TestList<Integer> list = new CopyOnWriteArrayList<>();

 

한계점

  • 쓰기 동작에서 배열 복사작업을 하기 때문에 성능 이슈가 발생할 수 있다.

 

잘못된 사용 방법

  • 스레드 동작 중 리스트의 요소를 더하거나 수정하는 것 (동시 수정 예외)

 

 

 

 

반응형

'Develop > Java' 카테고리의 다른 글

[Java] 싱글톤 패턴 : Thread safe & DCL  (0) 2023.07.16
[Java] this. 의미  (0) 2023.06.03
[Java] Atomic과 CAS(Compare and swap)  (0) 2023.05.29
[Java] Synchronized 동기화 예제  (0) 2023.05.14
[Java] Synchronized VS Reentrant 차이  (0) 2023.05.14
profile

억대 연봉을 위한 인간수업

@회뜨는참치

이 글이 당신에게 조금이라도 도움이 된다면 좋겠습니다.