자바의 동기화 키워드의 C # 버전?


313

C #에는 자체 버전의 java "동기화 된"키워드가 있습니까?

즉 자바에서는 함수, 객체 또는 코드 블록에 다음과 같이 지정할 수 있습니다.

public synchronized void doImportantStuff() {
   // dangerous code goes here.
}

또는

public void doImportantStuff() {
   // trivial stuff

   synchronized(someLock) {
      // dangerous code goes here.
   }
}

3
블록 형태는 잠금에 대한 참조가 필요합니다. 메소드 형식에서 잠금 객체는 암시 적으로 this입니다 (또는 정적 메소드의 경우 클래스 [this.class, getClass ()는 아니지만 클래스는 잠그지 않습니다).
Tom Hawtin-tackline

1
여전히 보호되지 않습니까? 나는 그 [MethodImpl(MethodImplOptions.Synchronized)]줄을 기억할 수 없기 때문에 항상 여기에옵니다 .
Bitterblue

1
두 번째 스 니펫이 컴파일되지 않을 것이라고 생각합니다 . 무언가 에 동기화 해야합니다 .
PoweredByRice

답변:


466

첫째, 대부분의 클래스는 스레드로부터 안전 할 필요가 없습니다. YAGNI 사용 : 실제로 사용하고 테스트한다는 것을 알고있을 때만 스레드 안전성을 적용 하십시오 .

메소드 레벨의 내용은 [MethodImpl]다음과 같습니다.

[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}

접근 자 (속성 및 이벤트)에서도 사용할 수 있습니다.

private int i;
public int SomeProperty
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    get { return i; }
    [MethodImpl(MethodImplOptions.Synchronized)]
    set { i = value; }
}

필드와 유사한 이벤트 기본적으로 동기화되지만 자동 구현 속성 은 그렇지 않습니다 .

public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized

개인적으로, 나는 MethodImpl그것이 잠기 this거나 typeof(Foo)최선의 방법에 위배되는 구현을 좋아하지 않습니다 . 선호하는 옵션은 자신의 잠금을 사용하는 것입니다.

private readonly object syncLock = new object();
public void SomeMethod() {
    lock(syncLock) { /* code */ }
}

필드와 유사한 이벤트의 경우 잠금 구현은 컴파일러에 따라 다릅니다. 이전 Microsoft 컴파일러에서는 lock(this)/ lock(Type)-그러나 최신 컴파일러에서는Interlocked 업데이트를 사용 하므로 불쾌한 부분없이 스레드로부터 안전합니다.

이를 통해보다 세부적인 사용법이 가능하며 Monitor.Wait/ Monitor.Pulseetc를 사용하여 스레드간에 통신 할 수 있습니다 .

관련 블로그 항목 (나중에 다시 방문 )


@earcam과 질문이 있습니까? 그 말은 사실입니다. 클래스의 대부분은 스레드 안전을 위해 테스트되지 않고, 스레드 안전 할 필요가 없다 가진 스레드 안전성은 성능에 영향을 미칠 것이다. 스레드에 대해 진정으로 걱정할 필요가있는 유형의 수는 매우 적습니다. 의도적으로 동기화 된 컬렉션, 멀티플렉서 등
Marc Gravell

4
나는 내가 간단히 말 했어야한다고 생각한다. "대부분의 클래스는 스레드로부터 안전 할 필요는 없지만" "모든 개발자는 동시성을 인식해야합니다". 돌이켜 보면 나는 그 숫자가 매우 작다는 것에 동의합니다 (그리고 분명히 당신이 한곳에서 한 번에 얻고 싶을 것입니다. 대부분의 클래스가 멀티 스레드 환경에서 잊어 버릴 수 있습니다). 댓글을 더 빨리 삭제하고 싶습니다 =)
earcam

6
Marc의 링크 된 블로그 게시물 은 .NET 4.0에서 2010 년 3 월 후속 조치를 취MethodImpl 했으며 필드와 유사한 이벤트는 이제 좋은 동기화 코드를 생성하므로 더 이상 고유 한 잠금을 사용할 필요가 없습니다.
Rory O'Kane 2016 년

2
요즘 대부분의 애플리케이션은 웹 기반이며 의존성 주입을 통해 인스턴스 재사용이 많고 복잡한 객체 수명주기에 의존하는 프레임 워크와 함께 제공됩니다. 요즘의 기본 사고 방식은 스레드 안전성 측면에서 잘못되는 경향이 있습니다.
Sheepy

1
@Elazar는 너무 늦었지만 지금은 기록적인 내용입니다. 프레임 워크를 변경하는 것은 .net 표준 /.net 코어 템플릿을 사용하여 프레임 워크를 만든 경우 csproj를 한 줄로 변경하는 것입니다. 타겟팅 그러나 이것에 대한 IDE 툴링은 단순히 끔찍합니다. 당신은 무엇을 바꿀 수 있고 무엇을 알아야하는지 알아야합니다.)
Marc Gravell

57
static object Lock = new object();

lock (Lock) 
{
// do stuff
}

9
lock 객체를 static ..으로 선언 하시겠습니까?
serg10

21
물론 모든 스레드가 참조를 전달하지 않고도 쉽게 액세스 할 수 있습니다.
Jan Gressmann

32
우리가 asker의 질문과 관련이 있다면 인스턴스 메소드에 대해 이야기하고 있습니다. 정적을 사용하면 스레드 1이 instance1.DoSomething ()을 호출하고 스레드 2가 instance2.DoSomething을 호출하면 두 번째 호출은 완전히 다른 객체 인 경우에도 차단됩니다. 누군가가 같은 객체 에서 DoSomething을 호출하지 않는 한 thread2의 호출은 차단되어서는 안됩니다 . 당신이 틀렸다고 말하는 것이 아니라 여기서 정적을 사용하는 효과를 이해하는 것이 중요합니다. 왜냐하면 인스턴스 단위가 아닌 전역 적으로 차단하여 성능이 저하 될 수 있기 때문입니다.
AaronLS

1
@AaronLS 객체가 자신보다 더 큰 범위에서 작업을 수행 할 때 매우 유용한 정적 잠금입니다. 예를 들어 항상 웹 서비스에서 발생합니다.
Thibault D.

3
OP가 요구하는 것과 다른 동작이므로 -1입니다. 이것은 인스턴스 잠금이 아니라 클래스 잠금입니다.
tster

39

C #에는 자체 버전의 java "동기화 된"키워드가 있습니까?

아니요. C #에서는 lock비동기 스레드에서 동 기적으로 작업 할 리소스를 명시 적으로 제공 합니다. lock블록을 엽니 다; 메소드 레벨에서는 작동하지 않습니다.

그러나 기본 메커니즘은 런타임에서 lock호출하여 Monitor.Enter(그리고 그에 따라 Monitor.Exit) 작동 하므로 비슷 합니다. Sun 문서 에 따르면 Java도 동일한 방식으로 작동합니다 .


3
이에 상응하는 "키워드"는 없지만 위의 Marc Gravell의 답변에서 볼 수 있듯이 [MethodImpl (MethodImplOptions.Synchronized)] 주석을 사용하여 메소드 레벨에서 동기화 할 수 있습니다.
MindJuice

1
Java의 synchronizedon 메소드는 기본적으로 synchronized (this.getClass())C #과 비슷하지 lock(typeof(this))않습니까?
스리 Harsha Chilakapati

2
@SriHarshaChilakapati 부분적으로 만 정확 synchronized하며 메소드 의 java 키워드는 다음 synchronized(this)과 같습니다 synchronized(class). 정적 메소드에서만 동작 합니다.
bvdb

7

전체 경로를 사용하여 [MethodImpl(MethodImplOptions.Synchronized)]다음과 같이주의하십시오.

[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]


1
또는 당신은 그냥 사용할 수 있습니다using System.Runtime.CompilerServices;
aloisdg codidact.com으로 이동

며칠 또는 몇 주 동안 C #을 프로그래밍 한 후 문을 사용하여 자동으로 삽입하는 것에 대해 아직 알지 못했을 때 그 의견을 썼습니다.
Traubenfuchs

1
당신은 적어도 3 DEVS 도움이하고의 좋은 :)
aloisdg 이동 codidact.com에

5

lock대신 문을 사용할 수 있습니다 . 나는 이것이 두 번째 버전 만 대체 할 수 있다고 생각합니다. 또한, 모두 기억 synchronized하고 lock필요 객체에서 작동 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.