2010-01-09 3 views
3

저는 개인 프로젝트를위한 비동기 메서드를 개발하려고하는데, 저는 참조 용 프레임 워크를 찾고 있습니다. 좀 더 밀접하게 비트와 볼트를 살펴 위해 .NET source code을 다운로드 한개체 필드를 로컬 변수에 집어 넣는 이점은 무엇입니까?

(개발자 의견, 반사경이 P는 우리에게 제공하지 않습니다 일) .NET을 많이,

어쨌든 클래스 다음과 같은 패턴을 발견했습니다 :

class SomeType 
{ 
    // ... 
    SomeClass m_Field; 
    // ... 
    SomeClass SomeMethod() 
    { 
    SomeClass localField = m_Field; 
    if (localField == null) 
    { 
     localField = new SomeClass(); 
     m_Field = localField; 
    } 
    return localField; 
    } 
} 

그런 패턴을 사용하면 어떤 이점이 있습니까?

은 내가 아는 한 패턴이 위 아래 하나보다 더 성능 현명하다 :

class SomeType 
{ 
    // ... 
    SomeClass m_Field; 
    // ... 
    SomeClass SomeMethod() 
    { 
    if (m_Field == null) 
    { 
     m_Field = new SomeClass(); 
    } 
    return m_Field; 
    } 
} 

아니면 내가 여기서 뭔가를 놓친 거지?

+1

구체적인 예를 들어 주시겠습니까? SomeClass에서 어떤 유형을 보았습니까? 그것은 어떤 종류의 소장품입니까? –

답변

2

은 많은 경우의 차이는 순전히 미학적 주관적이지만, 세 가지 이유는 마음에 와서 다른 대에 대한 일을 생각 :

  1. 스레드로부터의 안전성 : 잠금없는 알고리즘을 걱정해야 할 수도 있습니다 그러나 모든 동기화가 잠금을 통해 수행되면 문제가되지 않습니다.

  2. 성능 : 그것은 수도 어떤 경우에는 좀 더 빠르게 처리 될 수 있습니다,하지만 난 솔직히 대부분의 경우에서 차이를 만들 것입니다 의심한다.

  3. 예외 안전 : 종종 당신은 지역 주민에 중간 변경을 넣어 조심해야하고, 작업이 예외를 발생시키지 않고 완료 한 후에 만 ​​필드에 결과를 게시 할 수 있습니다. 이것은 아무도 필드 집합의 절반 만 가진 객체를 볼 것이므로 트랜잭션 메커니즘으로 작동합니다.

+1

스택 오버플로는 내가 인간이 아닐 수도 있다고 도전했습니다. 나는 여기에 새로운 오늘 재미 있습니다. –

+0

로봇 양복을 입고있는 사람들의 사진이 마음에 들지 않습니다! –

0

컴파일러가 필드를 메모리에 반복적으로 액세스하지 않고 레지스터로 읽어야한다는 힌트 일 수 있습니다. 첫 번째 버전이 으로 표시되어야하는 이유는 나와있는 두 번째 것보다 성능이 좋지 않은 일 것입니다. 컴파일러가 생성하는 코드와 거의 같습니다. 객체 필드를 레지스터로 읽어 들여 null인지 테스트하고 원하는대로 수정 한 다음 메모리의 객체 필드에 다시 씁니다.

2

이러한 접근 방식은 SomeMethod를 한 스레드에서 호출 할 때 상황을 보호하는 데 도움이되지만 null에 대해 m_Field를 확인한 후에는 다른 스레드로 제어가 전달되어 null로 설정됩니다. 그런 다음 컨트롤은 첫 번째 스레드로 반환되지만 여전히 m_Field! = null로 간주되어 NullReferenceException이 발생합니다.

리히터의 "CLR via C#"에서 약 두 단어가 기억납니다. 이벤트.

0

MS .NET JIT는 register allocation입니다. 그러한 단순한 경우, 임시 변수는 스택이 아닌 레지스터에 저장되어야합니다. 생성 된 x86 바이트 코드는 클래스 멤버가 null이 아닌 경우 두 번 읽히고 (null을 확인하기 위해 한 번, 한 번 반환하기 위해 한 번), null이 아닌 경우보다 빠르게 실행되어야합니다.그렇지 않으면 어떤 상황에서

코드 생성기가 즉시 일어날으로 객체 필드 일반적인 쓰기 변화 및 오브젝트 필드에서이 참조 될 때마다 읽을 수 있어야합니다, 스레드가 결코이 변경 사항을 볼 수 있습니다 오브젝트가 다른 thread에 의해 작성되고 그 반대도 가능합니다.

로컬 변수 변수를 사용하는 경우 컴파일러는 다른 스레드의 로컬에 액세스하는 것이 C#에서 허용하는 것이 아니므로 로컬 변수에 변경 사항을 쓸 필요가 없다고 (또는 스택에 저장하지 않아도됩니다) 가정합니다.

관련 문제