2009-12-22 2 views
0

잠금 문을 사용하지 않고 고성능 스레드 안전 구성 요소를 구현하면 성능상의 이유로 휘발성 및 연동 만 사용됩니다.잠금없이 다른 스레드에서 객체를 사용하지 않는 경우를 결정 하시겠습니까?

스레드 안전 인스턴스가 포함 된 클래스에 휘발성 참조 유형 멤버가 있습니다. 이 인스턴스는 몇 가지 작업에서만 스레드 안전하며 다른 작업에서는 스레드 안전하지 않습니다. 그 이유와 성능상의 이유로 어떤 경우에는 원본을 업데이트하는 대신 새 인스턴스를 만드는 것이 더 좋습니다. 특히 잠금 문을 사용하지 않기 때문에 실제로 더 빠르게 작동합니다.

휘발성 멤버는 언제든지 다른 인스턴스로 대체 될 수 있으므로 휘발성 키워드는 다중 스레드 환경에서 휘발성 키워드가 아무런 문제가 없음을 보장합니다.

이것은 물론 잘 작동하지만 그 유일한 문제는 이전 인스턴스의 가비지 수집입니다. 성능을 위해 구성 요소를 테스트했을 때 출시 된 인스턴스 가비지 수집에 너무 많은 시간을 소비하는 것으로 나타났습니다.

이제 이전 인스턴스를 재활용하는 방법을 모색 중입니다. 문제는 내가 교체 할 때 이전 인스턴스를 취할 수 없다는 것입니다.이 인스턴스를 계속 사용하는 다른 스레드가있을 수 있고이 인스턴스를 사용하지 않는 방법 (잠금없이)을 찾을 수 없기 때문에 상태를 재설정 할 수 있습니다. 더 이상.

잠금 문없이 이전 인스턴스를 사용하는 스레드가 없다는 것을 어떻게 보장 할 수 있습니까? (휘발성 및 연동 선호)

감사합니다.

+3

것은 정말 성능이 크게 감소 잠금을 사용 않습니다 말할 수없는 경우? – ironic

+0

나는 그 단어를 "결정적"으로 생각하고 그 것을 기억해야한다. –

+1

메모리 관리보다 미세 입자 제어가 필요한 경우 관리되는 응용 프로그램이 올바른 방법이 아닐 수 있습니다. 당신이 자물쇠를 던지는 곳에서 당신은 무엇을하고 있습니까? – GrayWizardx

답변

1

문제는 모든 스레드가 객체에 대한 참조를 스택으로 가져 와서 원하는대로 수행한다는 것입니다. 전반적인 잠금을 사용하지 않고 비 threadsafe 연산에 대해이를 방지 할 수있는 방법이 없습니다.

일반적으로 .NET 가비지 수집기에 대한 작업을 시도해서는 안됩니다. GC가 너무 오래 걸리는 이유를 확인하고이를 최적화하는 것이 좋습니다 (처음에는 너무 많은 인스턴스를 만들지 마십시오. place, 아마도 O (n^2) 연산으로 많은 인스턴스를 생성 할 것인가?)보다는 thread-safe 방식으로 인스턴스를 재사용하려고한다.

+0

많은 인스턴스가 디자인에 의해 만들어 지므로 그렇게해야합니다. 인스턴스를 재활용 할 수 있으면 가비지 수집이 전혀 필요하지 않습니다. – DxCK

0

멀티 스레드 응용 프로그램의 개체에서 작업을 수행하는 것이 안전한지 묻는 질문이 있습니다. 이것이 자물쇠의 정의입니다. .NET에서 제공하는 구조를 사용하는 것이 충분히 빠르지 않은 경우, 더 빨리 실행할 수있는 언어로 변경하는 것이 좋습니다.

+0

성능상의 이유로 처음부터 잠금을 사용하고 싶지 않기 때문에 재활용하고 싶습니다. 나는 인스턴스에 대한 액세스를 완전히 동기화 할 것을 요구하지 않는다, 나는 단지 다른 모든 것들이 인스턴스로 완료 될 때까지 기다리고 싶다. 그리고 나는 그걸로 무엇이든 할 것이다.이 정의는 원래의 잠금 정의보다 덜 일반적이다. 자물쇠없이 할 수 있습니다. – DxCK

2

여기서 구현하려는 것은 참조 횟수와 매우 비슷합니다 (COM 기억)? 증분/감소를 사용하여이 작업을 수행 할 수 있습니다. 참조 옆에 참조 카운터를 보관하십시오.

이 기술의 유일한 문제점은 개체 소비자가 개체 사용에 알맞게 의존하고 있다는 것입니다. 이로 인해 코드가 매우 약해집니다.

또 다른 질문은 AFAIK가 잠금 장치의 주요 성능 문제는 잠금 자체가 아니라 그것이 의미하는 메모리 장벽이라는 것입니다. 요점은 휘발성 변수에 대한 모든 액세스가 동일하다는 것입니다. 즉, 나는 휘발성 변수로 자물쇠를 대체하는 것을 얻지 못했습니다.

+0

나는 계산에 대해 생각했지만 문제는 참조를 가져 와서 카운터를 증가시키는 것은 원자 적 연산이 될 수 없기 때문에 스레드가 참조를 가져 왔지만 카운터를 아직 증가시키지 않았을 때 경쟁 조건을 만들 수 있습니다. 카운터가 0이고 이전 스레드가 카운트를 증가시키고 다른 작업을하는 동안 인스턴스를 재활용합니다. – DxCK

+0

휘발성에 대한 액세스가 장벽을 암시하는 것은 사실이 아닙니다. Java가 모든 x86 CPU와 같은 C# 메모리 모델에서 동일한 의미를 지니고 있다고 가정하면 휘발성 메모리에 대한 읽기 액세스가 특별하지 않아도 CPU 레벨에서의 의미 - 오직 쓰기에는 장벽/연동 명령이 필요합니다 (물론 바이트 코드 레벨에서는 읽기와 쓰기 모두 재 순서 지정과 같은 특수한 의미가 있습니다). – BeeOnRope

0

개체가 죽은 상태에서 다시 조사 할 수 있습니다. 즉, 개체가 으로 완료되면 실제로 다시 살아납니다.이것에는 수명주기의이 시점에서 어떤 참조도 존재할 수 없다는 이점이 있습니다. 그렇지 않으면 처음부터 최종 결정에 적용될 수 없었을 것입니다. 자세한 내용은 this 문서의 "Ressurection"장을 참조하십시오. 이제

, 그 정말 당신이 어떤 성과를 구입하거나 그것을하고 가치가 있는지, 내가 ;-)