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.