2012-04-01 5 views
1

나는 Interlocked.CompareExchange를 사용하여 더 빠르고 더 나은 방법을 알고 있지만 자물쇠에 국한되어 있다면 최선의 방법을 찾고 있습니다. 이전 값을 기준으로 두 개의 관련 필드를 수정하는 데 잠금을 사용하는 가장 효율적인 방법은 무엇입니까?

Joe Albahari says the following:

안전하게 그 이전의 값을 기반으로 새 ProgressStatus 객체를 할당 할 수도 있습니다

(예를 들어, 그것은 가능을 "증가"를 PERCENTCOMPLETE 값) - 코드의 하나 개 이상의 라인을 통해 잠금없이.

편집 : @ drch의 답변에 따라 업데이트 된 코드. 작은 \보다 효율적인 잠금을 사용하여이 작업을 수행 할 수 있는지 기다리는 중입니다. 이 락은 read, write 및 new 생성자를 모두 자물쇠에 가지고 있습니다. 더 작은 \보다 효율적인 잠금 장치를 원했습니다. 감사.

+1

IncreaseProgress 만, 정확한 하나 개의 스레드에 의해 실행된다? 두 개의 스레드가 동일한 statusCopy를 캐시하는 경우 여러 스레드가 실행 중이면 업데이트가 느슨해 질 수 있기 때문입니다. – aKzenT

+0

@ aKzenT 아니요. 많은 스레드가 한번에 IncreaseProgress를 호출한다고 가정합니다. 코드의 결함을 지적 해 주셔서 감사 드리며, 이것이 Joe Albahari가 이야기하고있는 하나의 라이너를 찾는 이유입니다. –

+0

http://msdn.microsoft.com/en-us/library/dd78zt0c.aspx를 보셨습니까? –

답변

1

언급 한 기사에서 한 줄에 잠금을 설정하면 나중에 Part 5의 고급 기술을 참조하는 것이 었습니다.

위의 코드에 관해서는 두 개의 잠금 장치 사이에서 경쟁 조건을 얻을 수 있습니다. 두 개의 쓰레드는 같은 값을 읽을 수 있고, 원하는 결과가 양쪽 모두 증가 할 때 같은 값을 쓸 수 있습니다.

잠금 전체 읽기 및 쓰기 이상 :

lock (_statusLocker) { 
    statusCopy = _status; 
    var newStatus = new ProgressStatus(statusCopy.PercentComplete + 10, statusCopy.StatusMessage); 
    _status = newStatus; 
} 

또는 단순히 :

lock (_statusLocker) { 
    _status = new ProgressStatus(_status.PercentComplete + 10, _status.StatusMessage); 
} 
+0

나는 자물쇠 안에 "새로운"것을하는 것이 실천에 좋지 않다는 인상을 받았다. +1을 한 행으로 가져 오는 것에 대해 +1하지만 자물쇠 안에 "새"가 없으면이 작업을 수행하는 방법이 있는지 궁금합니다. 감사. –

+0

"new"는 나쁘지 않습니다. 새로운 것은 점점 더 빨라진다. 어제 나는 GC를 포함하여 CPU 코어 당 초당 100m의 새로운 것을 할 수 있다고 벤치 마크했다. 그것에 대해 생각하지 마십시오. – usr

+1

어쨌든 : 성능 이상의 정확성. 자신이하는 일을 알지 못한다면 쓰레딩에 영리하지 마십시오. – usr

0

IMO는 불변 클래스를 사용하고 데이터 복사본으로 만 작업하므로 위의 코드를 사용하면 잠금없이 수행 할 수 있습니다. 읽기 및 쓰기 참조는 C# 스펙에 의해 원자 적으로 보장됩니다.

편집 : 그러나 스레드 동기화는 *** AB, 그래서

편집 ... 좀 더 의견을 듣고 싶습니다 : 내가 코멘트에서 지적 또한는 결함이있다 메소드에서 하나 이상의 스레드가 호출되는 경우 코드에서. 이 경우 업데이트가 손실 될 수 있습니다.

+2

'연동'을 사용하면 자물쇠 만 피할 수 있으며, OP는 명시 적으로 그 일을 원하지 않는다고 말했습니다. – CodesInChaos

+0

내가 말하고자하는 것은 자물쇠를 사용하지 않아도 ProgressStatus는 항상 좋은 상태에 있으며 진도를 읽는 누군가에게 얼룩이 진 값이나 이상한 행동이 없다는 것입니다. 그러나 주석에서 지적한대로 진행 상황에 대한 업데이트가 손실 될 수 있지만 잠금은이를 방지하기 위해 아무 것도하지 않았습니다.원래의 코드에서 그는 자물쇠가 자물쇠가없는 것보다 똑같은 (잘못된) 효과를 얻지 못한 채 할 수있었습니다. – aKzenT