Java에서 최상의 동시성 목록 선택 [닫기]


98

내 스레드 풀에는 고정 된 수의 스레드가 있습니다. 이 스레드가 필요 쓰기읽기 자주 공유 목록에서.

그렇다면 java.util.concurrent이 경우 패키지의 어떤 데이터 구조 (목록이 더 좋으며 모니터가 없어야 함) 가 가장 좋습니까?


5
컬렉션으로 무엇을 하려는지에 따라 다릅니다. 내 블로그 게시물을 참조하십시오 (.Net에 관한 것이지만 개념은 동일합니다). .NET Framework를 사용하여 올바른 스레드 안전 코드를 작성할 수있을 가능성은 거의 없습니다 List.
SLaks

1
이제 CopyOnWriteArrayList를 사용 하고 있지만 ConcurrentModificationException 예외가 가끔 발생합니다.
象 嘉 道

2
사람들이 더 잘 대답 할 수 있도록 컬렉션으로 무엇을하고 있는지에 대한 자세한 정보를 포함하세요. 그렇지 않으면 추측 일뿐입니다.
mattsh 2011

2
ConcurrentModificationException동기화 문제가 원인 이 아닐 수 있습니다. 예를 들어 컬렉션에서 요소를 제거하려고하는 컬렉션에 대한 for 루프에서도 발생합니다.
toto2 2011

1
나는 그것이 패키지의 일부가 아니라는 것을 알고 있지만 누군가가 시도 Vector했습니까?
WesternGun

답변:


96

더 낫다 List

유일한 List 구현 java.util.concurrentCopyOnWriteArrayList 입니다. Travis Webb이 언급 한대로 동기화 된 목록 옵션도 있습니다.

즉, 당신은 그것이 필요 List합니까? 동시 Queues 및 Maps에 대한 더 많은 옵션이 있으며 ( Sets에서 Maps를 만들 수 있음 ) 이러한 구조는 공유 데이터 구조로 수행하려는 많은 유형의 작업에 가장 적합한 경향이 있습니다.

대기열의 경우 많은 옵션이 있으며 가장 적합한 옵션은 사용 방법에 따라 다릅니다.


14
CopyOnWriteArrayList쓰기 비용이 매우 비싸다는 단점이 있습니다 (하지만 읽기 비용이 저렴합니다). 쓰기를 많이하는 경우 동기화 된 목록 또는 대기열을 사용하는 것이 좋습니다.
Peter Lawrey 2011

67

모든 Java 컬렉션은 다음과 같이 스레드로부터 안전하도록 만들 수 있습니다.

List newList = Collections.synchronizedList(oldList);

또는 새로운 스레드 안전 목록을 만들려면 :

List newList = Collections.synchronizedList(new ArrayList());

http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#synchronizedList(java.util.List)


7
이런 이유로 java.util.concurrent에서 목록 구현을 찾을 수 없습니다. 음, 메소드ConcurrentHashMap있어도 Collections.synchronizedMap있습니다.
aioobe

7
에서 Javadocs를 읽으십시오 ConcurrentHashMap. 동기화 구현의 세부 사항이 다릅니다. 기본적으로 synchronized메서드를 사용하면 CollectionsJava 모니터에서 클래스를 래핑합니다. ConcurrentHashMap더 영리한 동시성 기능을 사용합니다.
Travis Webb 2011

1
네. 그래도 마지막 문장은 유효하지 않습니다.
aioobe

1
모니터를 사용하면 프로그램의 성능이 정말 나쁩니다 :-(
象 嘉 道

5
추가하기 만하면 newList에 대한 반복은 스레드로부터 안전하지 않습니다. !!
bluelurker 2017 년

9

목록의 크기가 고정 된 경우 AtomicReferenceArray를 사용할 수 있습니다 . 이렇게하면 슬롯에 대한 인덱스 업데이트를 수행 할 수 있습니다. 필요한 경우 목록보기를 작성할 수 있습니다.


6

Paul Martin의 "잠금없는 실용적인 이중 연결 목록"을 기반으로 Doug Lea가 작성한 ConcurrentDoublyLinkedList 를 살펴볼 수 있습니다 . java.util.List 인터페이스를 구현하지 않지만 List에서 사용할 대부분의 메소드를 제공합니다.

javadoc에 따르면 :

Deque (양방향 대기열)의 동시 연결 목록 구현. 동시 삽입, 제거 및 액세스 작업은 여러 스레드에서 안전하게 실행됩니다. 이터레이터는 약하게 일관성 이 있으며 이터레이터 생성 시점 또는 생성 이후 특정 시점에서 데크의 상태를 반영하는 요소를 반환합니다. 그들은 할 수 없습니다 ConcurrentModificationException를 던져, 그리고 다른 작업과 동시에 진행할 수있다.


5

ConcurrentLinkedQueue잠금없는 대기열을 사용합니다 (최신 CAS 명령어 기반 ).


7
... List인터페이스를 구현하지 않습니다 .
aioobe 2011

1
eSniff, List.set(int index, Object element)ConcurrentLinkedQueue로 어떻게 구현 하시겠습니까?
John Vint 2011

4
대부분의 List특정 메서드는 Queue(예를 들어 특정 인덱스에서 추가 / 설정)을 사용하여 구현할 수 없거나 일종의 구현이 가능하지만 비효율적입니다 (인덱스에서 가져 오기). 그래서 나는 당신이 그것을 정말로 감쌀 수 있다고 생각하지 않습니다. 즉, QueueOP가 .NET Framework가 필요한 이유를 실제로 설명하지 않았기 때문에 a의 제안 은 괜찮다고 생각합니다 List.
ColinD 2011

1
@ColinD 그게 내가 원하는 대답입니다. CLQ를 목록으로 래핑 할 수없는 이유가 있습니다. 동의하지만 대기열 인터페이스를 배제 할 수 없습니다.
John Vint 2011

1
❗️ 다음 사항에 주목할 가치가 있습니다. "대부분의 컬렉션과 달리 size 메서드는 일정한 시간 작업이 아닙니다. 이러한 대기열의 비동기 특성으로 인해 현재 요소 수를 확인하려면 요소 순회가 필요합니다."
Behrang Saeedzadeh

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.