티스토리 뷰

* 동기화는 둘 이상의 쓰레드가 서로 작업을 덮어쓰지 않고 공유 리소스(자원)에 안전하게 액세스할 수 있는 방법.

 

* 임계영역(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
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함