2012-09-20 2 views
2

하나의 스레드가 연결된 목록에 쓰고 다른 스레드가 연결된 목록을 처리하도록하여 속도를 높이려고합니다.닷넷에서 스레드 우선 순위를 낮추십시오.

어떤 이유로 링크 된 목록에 쓰는 방법으로 링크 된 목록에서 우선 순위가 낮은 스레드를 읽는 메서드와 작업으로 만드는 경우 프로그램이 훨씬 빠르게 완료됩니다. 할 때 즉 내가 fastests 결과를 experiense :

Task.Factory.StartNew(AddItems); 

new Thread(startProcessingItems) { Priority = ThreadPriority.Lowest }.Start(); 

while(completed==false) 
    Thread.Sleep(0); 

아마 첫 번째 작업은 내가 두 번째 방법을 낮은 우선 순위를 설정하면 전반적으로 모든 것이 빠르게 완료됩니다 왜 다른 스레드에 비해 너무 많은 추가 작업을하고 있기 때문에 .

는 어쨌든 지금은 내 질문에 ThreadPriority = 최저와startProcessingItems 실행됩니다. 가장 높은 우선 순위로 변경하려면 어떻게해야합니까? 해당 메서드에서 새 작업을 만들면 낮은 우선 순위로 실행됩니까? 기본적으로 startProcessingItems는 목록으로 끝나고 그 목록이 있으면 가장 우선 순위가 높은 실행을 시작하려고합니다.

답변

5

이것은 좋은 접근 방법이 아닙니다. 먼저 LinkedList<T>은 스레드로부터 안전하지 않으므로 두 스레드로 쓰고 읽으면 경쟁 조건이 발생합니다.

더 나은 방법은 BlockingCollection<T>을 사용하는 것입니다. 이렇게하면 스레드 안전성에 대한 걱정없이 아이템을 추가 (제작자 스레드)하고 항목 (소비자 스레드)을 읽을 수 있습니다. 스레드 안전성이 보장됩니다.

읽기 스레드는 foreach에서 blockingCollection.GetConsumingEnumerable()을 호출하여 요소를 가져올 수 있으며 쓰기 스레드는 요소를 추가하기 만하면됩니다. 읽기 스레드는 이 자동으로을 차단하므로 우선 순위를 망칠 필요가 없습니다.

쓰기 스레드가 "완료"되면 CompleteAdding을 호출하면 읽기 스레드가 자동으로 완료됩니다.

+0

자물쇠를 사용하는 항목을 추가하거나 제거 할 때마다 listLock이라는 자물쇠가 있습니다. 하지만 대신 blockingCollection을 사용하겠습니다. +1 감사합니다 –

+1

@TonoNam Locking은 경쟁 조건 문제를 해결할 수 있지만 BC가 훨씬 뛰어납니다. 새로운 Concurrent 컬렉션은 대부분의 경우 일반 컬렉션을 잠그는 것보다 훨씬 뛰어납니다. –

+0

고마워요. 나는 다른 어떤 장소보다 여기에서 더 많이 배운다. –

2

스레드/프로세스 우선 순위를 변경하지 않고 고유 한 디자인을 변경하여 프로그램의 성능을 향상시킬 수 있습니다.

문제의 큰 부분은 당신이 busywait하고있는 것입니다 : 이것은 더 생산적인 작업을위한 CPU 사이클을 많이 소비하는 결과

while(completed==false) 
    Thread.Sleep(0); 

를, 그리고 왜 우선 순위가 더 빨리 실행할 수 있어요 낮추는 것 . 만약 당신이 busywaiting 그 다음에는 더 이상 문제가되지 않습니다.

리드가 제안했듯이 BlockingCollection은 이러한 상황에 맞게 조정됩니다. 제작자 스레드는 Add을 사용하여 항목을 추가하고 소비자 스레드는 Take을 사용하여 제거 할 항목이 더 이상 없을 경우 메서드가 단순히 차단된다는 것을 알 수 있습니다.

또한 저장할 수있는 Task 만들고 다른 작업 (CPU 사이클을 낭비하지 않고) 끝날 때까지 메인 스레드 대기를 가지고 Task.Result 또는 Task.Wait를 사용합니다. (당신이 스레드를 사용하는 경우 직접 당신은 Join를 사용할 수 있습니다.)

+0

고마워요. 나는 대신에 세마포어를 사용할 것이다. 그러나 때로는 목록에 더 많은 항목이있을 때까지 기다려야하는 한 스레드에서만. 대신 item.Next! = null'을 기다려야 스레드를 동기화해야합니까? 그렇다면 어떻게해야합니까? 나는 하나의 쓰레드가 링크 된리스트에 쓰고 다른 쓰레드가 그 쓰레드와 아이템을 읽도록한다. –

+1

@TonoNam Reed와 내가 말했듯이, 당신은'BlockingCollection'을 사용해야합니다. 'Take'를 사용하면 제거 할 항목이있을 때까지 자동으로 대기하고 모든 메소드가 원자 적으로 표시되도록합니다. – Servy

2

을 리드하고 Servy가 말한 외에도 :

스레드 우선 순위 프로세스 우선 순위를 기준으로합니다.

Windows 스케줄러는 스레드 시간을 예약 할 때 다른 모든 스레드를 고려합니다. 우선 순위가 높은 쓰레드는 인위적으로 나머지 시스템의 속도를 늦출 수있는 다른 쓰레드로부터 시간을 많이 소비한다. 시스템에 스레드에게 우선 순위를 부여하지 않을 이유가 없습니다. 우선 순위는 다른 것이 CPU를 빼앗아 간 경우에만 효과가 있습니다. 이는 이유가 있습니다. CPU가 스레드에서 멀리 떨어져있는 것이 아니라면 가장 높은 우선 순위로 마술처럼 빠르게 실행되지 않습니다.

스레드 우선 순위를 높음으로 설정하는 것은 거의 항상 잘못된 행동입니다.

두 스레드 간의 동기화 오버 헤드가 발생할 가능성이있는 성능 향상을 없앨 수 있습니다.

또한 Thread.Sleep (0)은 같은 우선 순위의 스레드로만 시간을 보류하고 실행할 준비가되어 있습니다. 스레드 부족으로 이어질 수 있습니다. http://msdn.microsoft.com/en-us/library/d00bd51t(v=vs.80).aspx

관련 문제