2012-08-03 2 views
4

매트릭스를 만들기 위해 동시 해시 맵을 사용했습니다. 범위는 100k입니다. 40 개의 스레드를 만들었습니다. 각 스레드는 행렬의 해당 요소에 액세스하여이를 수정하고 행렬을 다음과 같이 다시 씁니다.동시 HashMap 반복자 : 스레딩에 얼마나 안전한가요?

ConcurrentHashMap<Integer, ArrayList<Double>> matrix = 
    new ConcurrentHashMap<Integer, ArrayList<Double>>(25); 

for (Entry(Integer,ArrayList<Double>)) entry: matrix.entrySet()) 
    upDateEntriesOfValue(entry.getValue());  

스레드 안전성을 찾지 못했습니다. 값은 종종 null로 반환되고 프로그램이 중단됩니다. thread safe.Or 스레드 안전하고 다른 곳에서 버그가 있습니다. 한 가지는 내 프로그램이 단일 스레드 모드에서 충돌하지 않는다는 것입니다.

답변

11

iterator은 실제로 ConcurrentHashMap의 스레드로부터 안전합니다.

하지만 코드에서 스레드로부터 안전하지 않은 내용은 ArrayList<Double>입니다. 이 데이터 구조로 인해 문제점이 발생할 수 있습니다.

필요에 따라 concurrent data structure을 사용할 수 있습니다. ConcurrentHashMap가 스레드 안전합니다

+0

동기화 된 arraylist를 사용하도록 제안 하시겠습니까? – thetna

+0

동기화 된 arraylist는 한 번에 하나의 스레드에서만 액세스하므로 작동합니다. 그러나 요소를 추가하고 읽는 방법에 따라 미리 크기를 알고 특정 인덱스에 액세스하려는 경우''LinkedBlockingQueue' 또는 java.util.concurrent.atomic 배열을 사용해보십시오. 대부분 당신의 필요에 달려 있습니다. –

+0

동기화 된 배열 목록을 사용해 보셨습니까? 문제가 해결 되었습니까? –

1

은지도에 액세스하지만 Lists 여러 스레드가 동시에 그렇게 같은 목록 인스턴스에서 작동 수정하는 동안 thread-safelist를 사용할 수 있는지, thread-safe 할 필요를 봉사했다.

ConcurrentHashMap에 대한 작업은 밋밋하지만 스레드가 ArrayList이되면 synchronized이 아니므로 다중 스레드가 동시에 스레드에 액세스 할 수있어 스레드로부터 안전하지 않게됩니다. 당신이 synchronized block 목록에서 수정을 수행 할 수 있습니다

2

매트릭스에 대한지도를 사용하여 정말 비효율이며, 당신이 그것을 사용하는 방식으로, 심지어 스파 스 배열을 특히 잘 지원하지 않습니다.

각 행 (또는 더 나은 경우 열)을 잠그는 이중 [] []를 사용하는 것이 좋습니다. 행렬이 충분히 작 으면 하나의 CPU 만 사용하는 것이 더 좋을 수 있으므로 상당히 절약 할 수 있습니다 오버 헤드의.

코어가없는 것보다 더 많은 스레드를 만들 것을 제안합니다. CPU 집약적 인 작업의 경우 스레드를 더 많이 사용하는 것이 더 빠르지 않고 느려질 수 있습니다.

매트릭스는 최대

에서 100,000 * 50

편집이다 : 수행중인 작업에 따라, 당신이 다른 각각의 긴 치수를 처리 할 수 ​​있도록 먼저 짧은 치수를 확인하실 것입니다 쓰레드를 효율적으로 처리한다.

예컨대

double[][] matrix = new double[50][100*1000]; 
for(int i=0;i<matrix.length;i++) { 
    final double[] line = matrix[i]; 
    executorService.submit(new Runnable() { 
     public void run() { 
      synchronized(line) { 
       processOneLine(line); 
      } 
     } 
    }); 
} 

이것은 당신이 그들이 어떤 데이터 구조를 공유하지 않기 때문에 동시에 실행하는 스레드를 모두 할 수 있습니다. 그들은 또한 메모리에서 연속적이고 가능한 한 효율적으로 저장되기 때문에 각 더블을 효율적으로 액세스 할 수 있습니다. 즉 100K 복식은 약 800KB를 사용하지만 List<Double>은 2800KB를 사용하며 각 값은 메모리에 무작위로 정렬 될 수 있습니다. 즉, 캐시가 훨씬 더 많이 작동해야합니다.

감사하지만 사실 난 총

80 개 코어 80 코어 효율적 두 개 사에 긴 줄을 깰 그래서 당신이 바쁜 모든 코어를 유지할 수 있습니다, 또는 발견 할 수 있습니다 사용하려면이 한 번에 두 가지 이상의 작업을 수행하는 방법.

+0

충분한 코어가 있습니다. 저에게 중요한 문제는 아닙니다. 매트릭스는 ** 100k * 50 **에서 최대 – thetna

+0

정확히 40 코어를 가진 사람은 많지 않습니다. 'Runtime.availableProcessors()'를 사용하여 모든 CPU를 사용하고 있는지 확인하십시오. –

+0

감사하지만 실제로 나는 총 80 코어 있습니다. – thetna