메모
이 문서는 기능 사양입니다. 사양은 기능의 디자인 문서 역할을 합니다. 여기에는 기능 디자인 및 개발 중에 필요한 정보와 함께 제안된 사양 변경 내용이 포함됩니다. 이러한 문서는 제안된 사양 변경이 완료되고 현재 ECMA 사양에 통합될 때까지 게시됩니다.
기능 사양과 완료된 구현 간에 약간의 불일치가 있을 수 있습니다. 이러한 차이는 관련LDM(언어 디자인 모임) 노트에서 캡처됩니다.
사양문서에서 기능 스펙릿을 C# 언어 표준에 채택하는 과정에 대해 더 알아볼 수 있습니다.
챔피언 이슈: https://github.com/dotnet/csharplang/issues/7104
요약
System.Threading.Lock가 lock 키워드와 어떻게 특수하게 상호 작용하는지를 설명합니다 (EnterScope 메서드를 내부적으로 자동 호출하여).
가능한 경우 형식의 실수로 오용되지 않도록 정적 분석 경고를 추가합니다.
동기
.NET 9는 기존 모니터 기반 잠금에 대한 더 나은 대안으로 새로운 System.Threading.Lock 형식 도입했습니다.
C#에 lock 키워드가 있으면 개발자가 이 새 형식으로 사용할 수 있다고 생각할 수 있습니다.
이렇게 하면 이 형식의 의미 체계에 따라 잠기지 않고 대신 다른 개체로 처리하고 모니터 기반 잠금을 사용합니다.
namespace System.Threading
{
public sealed class Lock
{
public void Enter();
public void Exit();
public Scope EnterScope();
public ref struct Scope
{
public void Dispose();
}
}
}
상세 디자인
lock 문(§13.13)의 의미가 System.Threading.Lock 형식의 특정 사례로 변경됩니다.
형식
lock의 문서lock (x) { ... }
x형식의 표현인System.Threading.Lock을 포함하는 은(는), 정확히와(과) 동일하다.및using (x.EnterScope()) { ... }System.Threading.Lock는의 형태를 가져야 합니다.namespace System.Threading { public sealed class Lock { public Scope EnterScope(); public ref struct Scope { public void Dispose(); } } }x은 reference_type의 표현으로, 정확히 다음과 같습니다: [...]
셰이프가 완전히 확인되지 않을 수 있습니다(예: Lock 형식이 sealed않은 경우 오류나 경고가 없음). 하지만 기능이 예상대로 작동하지 않을 수 있습니다(예: 기능이 파생 형식이 없다고 가정하므로 Lock 파생 형식으로 변환할 때 경고가 발생하지 않음).
또한 형식을 업캐스트할 때 암시적 참조 변환(System.Threading.Lock)에 새 경고가 추가됩니다.
암시적 참조 변환은 다음과 같습니다.
- 어떤 reference_type에서
object및dynamic로.
- 참조 유형이(가)
System.Threading.Lock로 알려졌을 때 경고가 보고됩니다.- class_type
S에서 class_typeT로, 단S가T에서 파생된 경우에만 가능합니다.
S이System.Threading.Lock인 것으로 알려지면 경고가 보고됩니다.- 어떤 class_type
S에서 어떤 interface_typeT로,S이T을 구현하는 경우에 가능합니다.
S이System.Threading.Lock인 것으로 알려지면 경고가 보고됩니다.- [...]
object l = new System.Threading.Lock(); // warning
lock (l) { } // monitor-based locking is used here
이 경고는 동등한 명시적 변환에도 발생합니다.
컴파일러는 object변환한 후 인스턴스를 잠글 수 없는 경우에 경고를 보고하지 않습니다.
- 변환이 암시적이고 개체 같음 연산자 호출의 일부인 경우
var l = new System.Threading.Lock();
if (l != null) // no warning even though `l` is implicitly converted to `object` for `operator!=(object, object)`
// ...
경고를 회피하고 모니터 기반 잠금을 강제로 사용하려면 다음을 사용할 수 있습니다.
- 일반적인 경고 억제 수단(
#pragma warning disable) -
MonitorAPI를 직접 -
object AsObject<T>(T l) => (object)l;같은 간접 캐스팅.
대안
다른 형식이
lock키워드와 상호 작용하는 데 사용할 수 있는 일반적인 패턴을 지원합니다. 이는ref struct제네릭에 참여할 수 있을 때 구현될 수 있는 향후 작업입니다. LDM 2023-12-04에서 논의했습니다.기존 모니터 기반 잠금과 새
Lock(또는 향후 패턴) 간의 모호성을 방지하기 위해 다음을 수행할 수 있습니다.- 기존
lock문을 다시 사용하는 대신 새 구문을 소개합니다. - 새 잠금 형식을
struct로 지정해야 합니다 (기존lock은 값 유형을 허용하지 않음). 구조체에 지연 초기화가 있는 경우 기본 생성자 및 복사에 문제가 있을 수 있습니다.
- 기존
codegen은 더 이상 사용되지 않는 스레드 중단에 대해 강력해질 수 있습니다.
형식 매개 변수에 대한 잠금은 항상 모니터 기반 잠금을 사용하므로
Lock형식 매개 변수로 전달되는 경우에도 경고할 수 있습니다.M(new Lock()); // could warn here void M<T>(T x) // (specifying `where T : Lock` makes no difference) { lock (x) { } // because this uses Monitor }그러나 바람직하지 않은 목록에
Lock저장할 때 경고가 발생합니다.List<Lock> list = new(); list.Add(new Lock()); // would warn hereSystem.Threading.Lock과using에서await사용을 방지하기 위해 정적 분석을 포함할 수 있습니다. 즉,using (lockVar.EnterScope()) { await ... }같은 코드에 대해 오류나 경고를 발생시킬 수 있습니다. 현재는Lock.Scope이ref struct이기 때문에 해당 코드는 어차피 불법이어서 필요하지 않습니다. 그러나ref struct을async메서드에 허용하거나Lock.Scope가ref struct이 되지 않도록 변경한 경우, 이 분석이 유익해질 것입니다. 또한 나중에 구현되는 경우 모든 잠금 형식이 일반 패턴과 일치하는지를 고려해야 할 가능성이 있습니다. 일부 잠금 형식은await과 함께 사용할 수 있으므로, 이를 위한 옵트아웃 메커니즘이 필요할 수 있습니다.) 또는, 이는 런타임의 일부로 제공되는 분석기로 구현할 수 있습니다.값 형식을
lock수 없다는 제한을 완화할 수 있습니다.- 새
Lock형식의 경우(API 제안이class에서struct로 변경된 경우에만 필요) - 는 나중에 구현될 때 모든 형식이 참여할 수 있는 일반 패턴입니다.
- 새
lock내에서async사용되지 않는await메서드에서 새lock허용할 수 있습니다.- 현재
lock를 리소스로 사용하여using이ref struct로 낮춰지면서 컴파일 시 오류가 발생합니다. 해결 방법은lock별도의 비async메서드로 추출하는 것입니다. -
ref struct Scope사용하는 대신Lock.EnterLock.Exittry/ 및finally메서드를 내보낸다. 그러나Exit메서드는Enter과 다른 스레드에서 호출될 경우 반드시 예외를 던져야 하므로, 이러한 상황을 처리하기 위해 스레드 조회를 포함하며, 이는Scope를 사용하면 방지됩니다. -
using본문 내에ref struct이 없는 경우,async메서드에서await을 사용하여using을 컴파일하는 것이 가장 좋습니다.
- 현재
디자인 회의
-
LDM 2023-05-01:
lock패턴을 지원하기 위한 초기 결정 - LDM 2023-10-16: .NET 9의 작업 집합에 포함됨
-
LDM 2023-12-04: 일반 패턴을 거부하고,
Lock유형에 대한 특수 처리를 허용하며 정적 분석 경고를 추가함.
C# feature specifications