| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- unity sparkmain(clone)
- raycast
- unity korea
- sparkmain(clone)
- 유니티
- list clear
- 너비탐색
- Simulation
- GetComponent
- 최소신장트리 mst
- 디지털트윈
- 습관형성 #직장인자기계발 #오공완
- sparkmain(clone) 무한생성
- articulation body
- Unity
- dfs
- 최단거리 알고리즘
- 트리구조
- 크루스칼
- 티스토리챌린지
- 오블완
- 행동트리
- 깊이탐색
- 드롭다운
- 유니티 sparkmain(clone)
- C#
- readonly
- removeAll
- navisworks api
- dropdown
- Today
- Total
낑깡의 게임 프로그래밍 도전기
Unity C# : Lock (잠금) 메커니즘 / 동기화 메커니즘 본문
두개의 박스가있는데 둘 다 첫번째 박스에 들어가는데 첫번째 박스가 차있으면 두번째 박스로 가게끔해야하는 상황.
만약 호출시기가 똑같으면 보통 알아서 각자 들어가는게 아니라 에러가 발생한다.
이럴 때 Lock 매커니즘을 적절히 사용하면 두 개뿐만 아니라 10개, 그 이상이 동시에 실행되는 상황에서도 안전하게 처리할 수 있다. 중요한 것은 동기화 블록을 통해 동일한 코드 영역에 대한 접근을 일관되게 제어하는 것.
동기화 메커니즘 사용
요약
lock(object T)
{
원하는 코드;
}
- Lock (잠금) 메커니즘: C#의 lock 문을 사용하여 첫 번째 박스를 확인하고 아이템을 넣는 부분을 잠그면, 다른 스크립트가 이 부분을 동시에 실행하지 않도록 할 수 있음.(특정 객체를 기준으로 다른 스레드가 동일한 코드 블록에 접근X)
private static readonly object _lock = new object();
void AddItemToBox(Item item)
{
lock (_lock)
{
if (IsFirstBoxEmpty())
AddToFirstBox(item);
else
AddToSecondBox(item);
}
}
작동 방식 설명
- 동기화 블록 설정: lock (_lock) 구문을 통해 _lock 객체를 기준으로 잠금 설정.
- 잠금 획득: 한 스레드가 lock 블록을 실행하면, _lock 객체에 대한 잠금을 획득하고 나서야 블록 내부의 코드를 실행.
- 다른 스레드 대기: 잠금을 획득한 스레드가 블록 내부의 코드를 실행하는 동안, 다른 스레드는 잠금이 해제될 때까지 대기.
- 잠금 해제: 블록 내부의 코드가 모두 실행되면, 잠금이 해제되고 다른 대기 중인 스레드가 잠금을 획득하여 블록 내부의 코드를 실행.
동시 실행 시나리오
이 메커니즘을 사용하면 다음과 같은 방식으로 동작합니다:
- 두 개의 스레드가 동시에 AddItemToBox 함수를 호출하려고 할 때, 먼저 호출한 스레드가 _lock 객체에 대한 잠금을 획득.
- 이 스레드는 블록 내부의 코드를 실행한 후 잠금을 해제.
- 두 번째 스레드는 첫 번째 스레드가 잠금을 해제한 후에야 블록 내부의 코드를 실행할 수 있음.
---------------------------------------------------------------------------------------------------------------------------------------------------------------
상세 추가 설명과 데드락 관련 내용 추가 : 아래 블로그 참조
lock()의 파라미터에는 임의의 객체를 사용할 수 있는데, 주로 object 타입의 private 필드를 지정한다.
즉, private object obj = new object() 와 같이 private 필드를 생성한 후, lock(obj)와 같이 지정한다.
특히, 클래스 객체를 의미하는 this를 사용하여 lock(this)와 같이 잘못 사용할 수 있는데, 이는 의도치 않게 데드락을 발생시키거나 Lock Granularity를 떨어뜨리는 부작용을 야기할 수 있다. 즉, 불필요하게 객체 전체 범위에서 lock을 걸어 다수의 메서드가 공유 리소스를 접근하는데 Lock Granularity를 떨어뜨리는 효과가 있으며 (주: 이 경우 필드나 속성들이 잠긴다는 의미는 아니며, 이들 필드나 속성을 계속 읽고 쓸 수 있음) , 또한 만약 외부에서 해당 클래스 객체를 lock 하고 그 객체 안의 메서드를 호출한 경우 그리고 그 메서드안에서 다시 lock(this)를 하는 경우, 이미 외부에서 잡혀있는 lock이 풀리기를 메서드 내에서 계속 기다릴 것이므로 데드락이 발생할 수 있다.
그리고 Critical Section 코드 블록은 가능한 한 범위를 작게하는 것이 좋은데, 이는 필요한 부분만 Locking한다는 원칙에 따른 것이다.
using System;
using System.Threading;
namespace MultiThrdApp
{
class MyClass
{
private int counter = 1000;
// lock문에 사용될 객체
private object lockObject = new object();
public void Run()
{
// 10개의 쓰레드가 동일 메서드 실행
for (int i = 0; i < 10; i++)
{
new Thread(SafeCalc).Start();
}
}
// Thread-Safe 메서드
private void SafeCalc()
{
// 한번에 한 쓰레드만 lock블럭 실행
lock (lockObject)
{
// 필드값 변경
counter++;
// 가정 : 다른 복잡한 일을 한다
for (int i = 0; i < counter; i++)
for (int j = 0; j < counter; j++) ;
// 필드값 읽기
Console.WriteLine(counter);
}
}
//출력 예:
// 1001
// 1002
// 1003
// 1004
// 1005
// 1006
// 1007
// 1008
// 1009
// 1010
}
}
https://www.csharpstudy.com/Threads/lock.aspx
C# lock 블럭 - C# 프로그래밍 배우기 (Learn C# Programming)
Thread-Unsafe의 예제 멀티쓰레드는 필드의 내용을 동시에 엑세스하여 잘못된 결과를 만들거나 출력할 수 있는데, 이를 Thread Unsafe 하다고 한다. 아래 예제는 여러 개의 쓰레드가 Thread-Safe하지 않은
www.csharpstudy.com
'Unity C#' 카테고리의 다른 글
| Unity C# : TriLibCore 사용 시 로드 파일 경로 반환 - 상편 -(StandaloneFileBrowser / UnityEditor) (0) | 2024.06.10 |
|---|---|
| Unity C# : 다양한 세이브(Save) 기능 옵션 소개 (0) | 2024.06.10 |
| Unity Bounds로 오브젝트의 경계와 중심 구하기 (0) | 2024.05.28 |
| 정적라이브러리와 동적라이브러리의 장단점 (0) | 2024.05.22 |
| Unity C# List 초기화 Clear와 RemoveAll 차이 (0) | 2024.05.20 |