내용 보기
작성자
관리자 (IP : 106.247.248.10)
날짜
2024-07-29 08:22
제목
[C#] [스크랩] async 메서드에서의 lock/Monitor.Enter/Exit 잠금 처리
Monitor 잠금은 스레드를 기억하는 유형입니다. 그래서, lock을 보유한 스레드만이 해제를 할 수 있습니다. 가령, 다음과 같이 다른 스레드에서 lock을 해제하려고 하면, internal class Program { static object _obj = new object(); static void Main(string[] args) { Monitor.Enter(_obj); // lock을 획득 Thread t = new Thread(() => { Monitor.Exit(_obj); // 다른 스레드에서 lock을 해제 }); t.Start(); t.Join(); } }
Unhandled exception. System.Threading.SynchronizationLockException: Object synchronization method was called from an unsynchronized block of code. at System.Threading.Monitor.Exit(Object obj) at Program.<>c.<Main>b__1_0()
internal class Program { static object _obj = new object(); static void Main(string[] args) { Console.WriteLine("Lock++"); Monitor.Enter(_obj); Console.WriteLine("Lock++"); Monitor.Enter(_obj); // 2번 잠금 Thread t = new Thread(() => { Monitor.Enter(_obj); // 다른 스레드에서 lock을 얻으려고 시도 Console.WriteLine("Thread 1"); Monitor.Exit(_obj); }); t.Start(); Console.WriteLine($"{DateTime.Now} Lock--"); Monitor.Exit(_obj); // 한 번 잠금을 해제 Thread.Sleep(5000); Console.WriteLine($"{DateTime.Now} Lock--"); Monitor.Exit(_obj); // 두 번 잠금을 해제 - 이 시점에 "Thread 1"이 출력됨 t.Join(); } }
Lock++ Lock++ 2024-07-26 오후 18:44:40 Lock-- 2024-07-26 오후 18:44:45 Lock-- // 5초 후 2번째 잠금이 해제되고 나서야 "Thread 1"이 출력됨 Thread 1
C# - Mutex의 비동기 버전 ; https://www.sysnet.pe.kr/2/0/13157
internal class Program { static object _obj = new object(); static async Task Main(string[] args) { lock (_obj) { // error CS1996: Cannot await in the body of a lock statement await Task.Delay(2000); } } }
internal class Program { static object _obj = new object(); static async Task Main(string[] args) { Monitor.Enter(_obj); await Task.Delay(2000); Monitor.Exit(_obj); // 실행 시 오류 } }
Unhandled exception. System.Threading.SynchronizationLockException: Object synchronization method was called from an unsynchronized block of code. at System.Threading.Monitor.Exit(Object obj) at Program.Main(String[] args) at Program.<Main>(String[] args)
public partial class Form1 : Form { object _obj = new object(); public Form1() { InitializeComponent(); } private async void Form1_Load(object sender, EventArgs e) { bool lockTaken = false; try { Monitor.Enter(_obj, ref lockTaken); await Task.Delay(2000); } finally { if (lockTaken) { Monitor.Exit(_obj); } } } }
private async void Form1_Load(object sender, EventArgs e) { lock (_obj) // 컴파일 오류: error CS1996: Cannot await in the body of a lock statement { await Task.Delay(2000); } }
private async void Form1_Load(object sender, EventArgs e)
{
bool lockTaken = false;
try
{
Monitor.Enter(_obj, ref lockTaken);
await Task.Delay(2000).ConfigureAwait(false);
}
finally
{
if (lockTaken)
{
Monitor.Exit(_obj); // 실행 시 오류: System.Threading.SynchronizationLockException: 'Object synchronization method was called from an unsynchronized block of code.'
}
}
}
namespace WinFormsApp1; public partial class Form1 : Form { SemaphoreSlim _sem = new SemaphoreSlim(1); public Form1() { InitializeComponent(); } private async void Form1_Load(object sender, EventArgs e) { _sem.Wait(); // Main 스레드에서 lock 획득 new Thread(() => { System.Diagnostics.Trace.WriteLine($"[{DateTime.Now}] --------------------- Thread called"); _sem.Wait(); // 사용자 스레드에서 lock 획득 시도 try { System.Diagnostics.Trace.WriteLine($"[{DateTime.Now}] --------------------- got Semaphore"); Thread.Sleep(2000); } finally { _sem.Release(); } }) { IsBackground = true }.Start(); try { await Task.Delay(5000).ConfigureAwait(false); // 5초 후에, } finally { _sem.Release(); // 스레드풀의 스레드에서 lock 해제 } } } |
출처1
https://www.sysnet.pe.kr/2/0/13697
출처2