C # : 정적 메서드가 여러 스레드에서 호출되면 어떻게됩니까?


93

내 응용 프로그램에는 동시에 여러 스레드에서 호출되는 정적 메서드가 있습니다. 데이터가 뒤섞 일 위험이 있습니까?

첫 번째 시도에서 메서드는 정적이 아니었고 클래스의 여러 인스턴스를 만들고있었습니다. 그 경우 내 데이터가 어떻게 든 뒤섞여있었습니다. 때때로 발생하기 때문에 이것이 어떻게 발생하는지 잘 모르겠습니다. 아직 디버깅 중입니다. 그러나 이제 방법은 지금까지 아무런 문제가 없습니다. 어쩌면 행운 일 수도 있습니다. 나는 확실히 모른다.


답변:


96

메서드 내부에서 선언 된 변수 ( " 캡처 된 "변수 제외)는 격리되어 있으므로 고유 한 문제가 발생하지 않습니다. 그러나 정적 메서드가 공유 상태에 액세스하면 모든 베팅이 해제됩니다.

공유 상태의 예는 다음과 같습니다.

  • 정적 필드
  • 공통 캐시에서 액세스 한 개체 (직렬화되지 않음)
  • 입력 매개 변수 (및 해당 객체의 상태)를 통해 얻은 데이터 (여러 스레드가 동일한 객체에 닿을 수있는 경우)

상태를 공유 한 경우 다음 중 하나를 수행해야합니다.

  • 이 (더 나은 공유 할 수 있습니다 일단 상태를 돌연변이하지 않도록주의 : 상태를 나타내며, 지역 변수로 상태의 스냅 샷을 사용 불변의 객체 - 즉 오히려 기준보다 whatever.SomeData반복을 읽고 whatever.SomeData 한 번 지역 변수로, 다음 변수를 사용하십시오-이것은 불변 상태에만 도움이됩니다!)
  • 데이터에 대한 액세스 동기화 (모든 스레드는 동기화해야 함)-상호 배타적이거나 (더 세분화 된) 리더 / 라이터

1
@Diego-그 댓글은 나를위한 것입니까, 아니면 @Holli를위한 것입니까?
Marc Gravell

Holli에게 답장에 실용적인 정보를 추가하기 위해.
Diego Pereyra 2010-06-14

1
@Marc "메서드 내에서 선언 된 변수 ("캡처 된 "변수의 가능한 예외 제외)가 격리되어 있습니다"에 완전히 동의 할 수 없습니다. 정적 메소드에서 선언 된 파일 핸들을 고려하십시오. 그러면 다른 스레드가 핸들을 사용할 때 한 스레드가 핸들에 액세스 할 수 있습니다. 예기치 않은 동작이 발생할 수 있습니다. 아니면 "캡처 된"변수도 "파일 핸들"을 의미합니까?
prabhakaran

9
@prabhakaran 파일 핸들이 메서드 변수이면 해당 호출자 에게만 범위가 지정 됩니다 . 다른 호출자는 다른 변수 와 대화 합니다 (메서드 변수는 호출 당). 이제 기본 파일에 대한 액세스 는 별도의 문제이지만 C # 또는 .NET과는 관련이 없습니다. 핸들이 공유되지 않으면이 시나리오가 가능하다면 일종의 뮤텍스 / 잠금을 기대할 수 있습니다.
Marc Gravell

29

네, 그냥 행운입니다. ;)

메서드가 정적인지 여부는 중요하지 않으며 데이터가 정적인지 여부는 중요합니다.

각 스레드에 자체 데이터 집합이있는 클래스의 개별 인스턴스가있는 경우 데이터가 뒤섞 일 위험이 없습니다. 데이터가 정적 인 경우 데이터 세트가 하나만 있고 모든 스레드가 동일한 데이터를 공유하므로 혼합하지 않을 방법이 없습니다.

별도의 인스턴스에있는 데이터가 여전히 엇갈리는 경우 데이터가 실제로 분리되지 않았기 때문일 가능성이 높습니다.


7
그 라인을 좋아했습니다- It doesn't matter if the method is static or not, what matters is if the data is static or not. 추가하자면, 정적 메서드의 범위 내에서 선언 된 지역 변수는 주어진 시나리오에서 신경 써야하는 데이터 부분을 형성하지 않습니다.
RBT

좋은 대답입니다. 많이 도왔습니다.
Fractal

15

정적 메서드는 여러 스레드에 적합해야합니다.

반면에 정적 데이터는 다른 스레드에서 동일한 데이터에 액세스하려는 시도를 제어하여 한 번에 하나의 스레드 만 데이터를 읽거나 쓰도록 제어해야하기 때문에 문제를 일으킬 수 있습니다.


2
여기서 키워드는 :-) 동기화입니다
G. Stoynev

2
독서는 동시에 일어날 OK이지만, 읽기와 동시에 작성하는 것은 예기치 않은 동작이 이어질 것
Freestyle076

9

MSDN 항상 말한다 :

이 형식의 모든 공용 정적 (Visual Basic에서 공유) 멤버는 스레드로부터 안전합니다. 모든 인스턴스 멤버는 스레드 안전이 보장되지 않습니다.

편집 : 여기에있는 사람들이 항상 그런 것은 아니며 이것이 적용되지 않는 사용자 생성 클래스가 아니라 BCL에서 이러한 방식으로 설계된 클래스에 분명히 적용됩니다.


3
휴! 마지막으로 MSDN 문서에서 자주 발견되는이 노트의 의미를 이해했습니다. 따라서 기본적으로 MS가 BCL에서 정적 메서드 (이 노트가 게시 된 곳)를 설계 할 때 해당 메서드의 범위를 벗어난 변수 / 멤버 / 상태에 액세스하지 않습니다. 메서드의 논리를 구현하기 위해서만 메서드 범위 지역 변수에 전적으로 의존합니다. 공유해 주셔서 매우 기쁩니다.
RBT

@Marcote, 그 반대 사실이 아닙니까? 인스턴스 멤버는 인스턴스 당 하나씩 있으므로 안전합니다. 그러나 정적 멤버는 해당 클래스의 모든 인스턴스에서 공유되기 때문에 스레드로부터 안전하지 않습니다. quora.com/…
Fractal

1
때에 따라 다르지. 기본적으로 인스턴스 멤버를 안전하게 취급하지 않습니다. 이것이 바로 전체 라이브러리 세트와 다른 많은 것들 사이에서 데이터 손상을 방지하는 이유입니다.
Marcote

1
좋아, 감사합니다 @Marcote. 나는 내가 배울 것이 많다는 것을 천천히 깨닫고있다.
Fractal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.