티스토리 뷰
* 동기화는 둘 이상의 쓰레드가 서로 작업을 덮어쓰지 않고 공유 리소스(자원)에 안전하게 액세스할 수 있는 방법.
* 임계영역(Critical section)
공유 리소스(자원)에 Thread safety하게 접근하는 영역
* Lock 키워드
보편적으로 동기화에 사용할 객체를 정의한다.
object lockObj = new object();
lock(lockObj) 상호 배제 잠금을 획득
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
int a = 5;
Thread thread1 = null;
Thread thread2 = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
thread1 = new Thread(new ThreadStart(WorkThread));
thread1.IsBackground = true;
thread1.Priority = ThreadPriority.Normal;
thread1.Start();
thread2 = new Thread(new ThreadStart(WorkThread2));
thread2.IsBackground = true;
thread2.Priority = ThreadPriority.Normal;
thread2.Start();
}
/// <summary>
/// Thread가 사용할 함수
/// Thread1,2 거의 동시에 시작. 실행 순서는 운영체제 스케줄러가 결정함. 알수없음.
/// </summary>
private void WorkThread()
{
Thread.Sleep(2000); //2초 대기
a = 1;
MessageBox.Show("" + a); // 1 표시 (실행 후 2초 뒤)
}
private void WorkThread2()
{
a = 2;
Thread.Sleep(3000); //3초 대기 >> a가 2에서 1로 값이 덮어씌여짐(a는 2초 대기니까)
MessageBox.Show("" + a); // 1 표시 (실행 후 3초 뒤)
}
}
}
a는 공유변수 이고, 실행 순서에 따라 값이 덮어씌워질 가능성이 있다. >> lock 사용하여 상호 배제 잠금
//해당 클래스에 객체 생성 필요
object lockObj = new object();
private void WorkThread()
{
while (true) // 반복문
{
// 1번.lockObj 상호배제 잠금
lock (lockObj) //해당 thread가 실행되는 동안 다른 쓰레드 접근 금지
{
// 2번 코드 실행
Thread.Sleep(2000); //2초 대기
a = 1;
}
// 4번. 상호 배제 잠금 해제
}
}
private void WorkThread2()
{
while (true)
{
// 3번.lockObj 상호배제 잠금 요청. 대기
lock (lockObj) //해당 thread가 실행되는 동안 다른 쓰레드 접근 금지
{
// 5번. 코드 실행
a = 2;
Thread.Sleep(3000); //3초 대기
MessageBox.Show("" + a); // 2 표시 (실행 후 5초 뒤)
}
// 6번. 상호배제 잠금 해제 >> 1번으로
// 파일 읽고 쓰기, 네트워크 전송,수신, DB 작업 ...
}
}
* Lock 키워드 주의사항
lock(obj)
{
...
// 대기상태(무한)
lock(obj)
{
...
} //교착 상태
...
} //상호 배제 잠금 해제
lock 안에 동일한 객체에 잠금을 요청 시 DeadLock 발생할 수 있다.
프로그램이 멈출 가능성이 있고, try catch에 잡히지 않기에 원인 파악도 힘들다.
* AutoResetEvent
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
int a = 5;
object lockObj = new object();
AutoResetEvent autoResetEvent = new AutoResetEvent(true); //첫번째 신호는 받은 상태로 변경 5 > 10 > 10
//AutoResetEvent autoResetEvent = new AutoResetEvent(false); // 10 > 10 > 10
Thread thread1 = null;
Thread thread2 = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
thread1 = new Thread(new ThreadStart(WorkThread));
thread1.IsBackground = true;
thread1.Priority = ThreadPriority.Normal;
thread1.Start();
thread2 = new Thread(new ThreadStart(WorkThread2));
thread2.IsBackground = true;
thread2.Priority = ThreadPriority.Normal;
thread2.Start();
}
/// <summary>
/// Thread가 사용할 함수
/// Thread1,2 거의 동시에 시작. 실행 순서는 운영체제 스케줄러가 결정함. 알수없음.
/// </summary>
private void WorkThread()
{
while (true) // 반복문
{
autoResetEvent.WaitOne(); //1번. 신호를 받을 때까지 대기한다.(기다리는 상태) //true 상태일 때, 두번째 신호를 대기한다.
// 3번. 실행
// 이후 다음 작업 진행되는 부분
MessageBox.Show("" + a);
}
}
private void WorkThread2()
{
while (true)
{
// 신호 보내기 전 영역 실행됨.
a = 10;
Thread.Sleep(5000); // 5초 대기
autoResetEvent.Set(); // 2번. 신호를 보낸다.
}
}
}
}
'2023~ > c#(.net framework)' 카테고리의 다른 글
C# .NET 주니어 1.멀티쓰레드 복습 (0) | 2025.02.10 |
---|---|
C# .NET 주니어 1.멀티쓰레드 (0) | 2024.05.21 |
WebApiConfig (0) | 2024.02.06 |
C# 윈폼_응용프로그램 개발 14 (0) | 2024.01.28 |
C# 윈폼_응용프로그램 개발 13 (0) | 2024.01.28 |