<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://trans.onionmixer.net/wiki/index.php?action=history&amp;feed=atom&amp;title=LazarusCompleteGuide%3A10.2</id>
	<title>LazarusCompleteGuide:10.2 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://trans.onionmixer.net/wiki/index.php?action=history&amp;feed=atom&amp;title=LazarusCompleteGuide%3A10.2"/>
	<link rel="alternate" type="text/html" href="https://trans.onionmixer.net/wiki/index.php?title=LazarusCompleteGuide:10.2&amp;action=history"/>
	<updated>2026-05-02T05:55:12Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>https://trans.onionmixer.net/wiki/index.php?title=LazarusCompleteGuide:10.2&amp;diff=3280&amp;oldid=prev</id>
		<title>Onionmixer: LCG 10.2 페이지 추가</title>
		<link rel="alternate" type="text/html" href="https://trans.onionmixer.net/wiki/index.php?title=LazarusCompleteGuide:10.2&amp;diff=3280&amp;oldid=prev"/>
		<updated>2013-03-13T07:29:44Z</updated>

		<summary type="html">&lt;p&gt;LCG 10.2 페이지 추가&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==스레드==&lt;br /&gt;
&lt;br /&gt;
스레드는 프로그램이 실행되는 장소이다. 프로그램이 하나 이상의 스레드를 가질 경우 여러 액션을 동시에 실행할 수 있다. 단일 프로세서 시스템에서는 각 스레드가 짧은 시간 슬롯 동안 실행이 허용되어, 동시에 여러 개의 액션을 실행할 수 있다는 인상을 심어준다. 이 전략을 시분할방식(timesharing)이라 부른다. 멀티프로세서 시스템에서는 하나 이상의 스레드가 실제로 동시에 실행되는 것이 가능하지만, 물론 시스템 내 CPU 수는 초과하지 않는다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
멀티스레드 애플리케이션을 생성하는 수고를 감수하는 이유에는 여러 가지가 있다. 그 중 하나는 사용자가 시간이 많이 소요되는 작업을 실행하는 동안에도 작업을 계속할 수 있도록 만들기 위해서이다. 또 다른 이유는 멀티프로세스 시스템의 모든 리소스를 활용하는 방식으로 동시에 여러 프로세서 집중적인 활동들을 실행해야 할 필요성을 들 수 있겠다. 한 스레드는 항상 하나의 프로세서에 의해 실행되므로 단일 스레드의 프로그램은 멀티프로세서 성능을 활용할 수 없다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
스레드를 사용 시 단점도 있으므로 해결하고자 하는 문제에 멀티스레드가 충분한 장점을 가져다주는지 항상 고려해야 한다. 멀티스레드 애플리케이션은 디버깅이 더 까다로운데, 스레드의 활동을 실행하는 데 소요되는 시간이 다양하기 때문이다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
모든 프로세스는 최소 하나의 스레드를 가지는데, 이는 먼저 모든 유닛의 초기화를 실행한 후 메인 프로그램의 시작으로 돌아간다. 이 스레드를 메인 스레드라고 부른다. 애플리케이션은 메인 스레드가 끝날 때 종료된다. 이는 스레드 안전(thread-safe)에 해당하지 않는 라이브러리를 호출할 수 있는 유일한 스레드이다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
프로세스의 모든 스레드는 동일한 기억 공간을 공유하므로 모두 전역 변수를 읽고 쓰는 것이 가능하다. 각 스레드는 고유의 스택과 고유의 레지스터 이미지를 가지므로 고유의 로컬 변수도 가진다. 즉, 로컬 변수를 다른 스레드로 전달하는 것이 문제가 될 수 있음을 의미한다; 스레드가 그들이 선언된 프로시저를 떠나면 더 이상 유효하지 않기 때문이다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
이는 문자열과 같은 참조 횟수(reference-counted) 객체에는 문제가 되지 않는다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
유닉스 체제는 (모놀리식 윈도우와 달리) 매우 모듈식(modular) 구조를 가지며 다수의 함수들이 초기설치 시 포함되어 있지 않으므로 추후 설치를 통해서만 추가된다. 이는 유닉스 체제에 필요한 리소스가 모두 설치되어 있는지 확신할 수 없음을 의미한다. 이는 POSIX 스레드 라이브러리에도 마찬가지인데, 이는 운영체제의 실행에 기본 요구사항이 아니기 때문이다. 그러한 확장된 기능은 필요 시 유닉스 체제로 라이브러리를 추가함으로써 설치된다. 따라서 우리는 적절한 리소스 관리자가 설치되어 있는지 주목해야 한다. 이는 cthreads 유닛을 프로그램에 연결시킴으로써 처리한다. 이는 프로그램 초기설정(initialization)에 pthreads 라이브러리를 로딩할 것이다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
이를 가능하게 하려면 cthreads 유닛을 이용하는 다른 유닛들보다 먼저 cthreads 유닛을 포함시켜야 한다. 아래 uses 절의 예를 들어보겠다:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
program myproject;&lt;br /&gt;
  uses&lt;br /&gt;
    {$IFDEF UNIX}&lt;br /&gt;
  cthreads,&lt;br /&gt;
    {$ENDIF}&lt;br /&gt;
    //... other units are declared after cthreads&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===TThread 클래스===&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;border: 1px solid black;&amp;quot;&lt;br /&gt;
|- style=&amp;quot;color: white; background-color: black;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;프로퍼티&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;설명&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;procedure Resume;&amp;#039;&amp;#039;&amp;#039;||스레드의 실행을 다시 시작한다. &lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;procedure Suspend;&amp;#039;&amp;#039;&amp;#039;||스레드를 일시정지시킨다. &lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;procedure Terminate;&amp;#039;&amp;#039;&amp;#039;||스레드에게 중단할 것을 신호로 보낸다. &lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;procedure Synchronize (AMethod: TThreadMethod);&amp;#039;&amp;#039;&amp;#039;||메인 스레드에 AMethod를 실행한다. AMethod는 객체의 타입 프로시저여야 한다.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;function WaitFor:&amp;#039;&amp;#039;&amp;#039;||정수; 스레드가 중단되길 기다리고 종료 상태를 리턴한다. &lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;property FreeOnTerminate: Boolean; [rw]&amp;#039;&amp;#039;&amp;#039;||스레드가 실행을 중단 시 스스로 해제(free)될 것인지를 나타낸다.&amp;lt;BR&amp;gt;기본 값은 False이다.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;property handle: TThreadID; [r]&amp;#039;&amp;#039;&amp;#039;||스레드 핸들을 리턴한다. &lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;property Priority: TThreadPriority; [rw]&amp;#039;&amp;#039;&amp;#039;||스레드 우선순위를 리턴한다. &lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;property Suspended: Boolean; [rw]&amp;#039;&amp;#039;&amp;#039;||스레드가 일시정지되었는지 나타낸다. &lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;property OnTerminate: TNotifyEvent; [rw]&amp;#039;&amp;#039;&amp;#039;||스레드가 중단 시 호출되는 이벤트. &lt;br /&gt;
|- style=&amp;quot;color: black; background-color: gray;&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; |표 10.6: TThread의 가장 중요한 메소드와 프로퍼티&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Execute 메소드 내 코드는 스레드가 실행 중일 때 실행된다. 스레드에 대해 로컬 저장소를 생성하려면 파생된 클래스에 필드를 추가해야 한다. TThread로부터 클래스를 파생할 때는 새 스레드를 생성하고, 해제(release)할 때는 스레드를 해제(release)한다. TThread 내 일부 메소드는 종료될 때까지 기다리는 것이 가능하다. 즉시 시작할 것인지, 이후에 시작할 것인지 나타낼 수도 있다. Terminated 프로퍼티는 그것이 종료되어야 함을 의미한다. 이 프로퍼티는 사실상 유일한 플래그로, 어떤 액션도 취하지 않는다. 수시로 확인하는 내용은 Execute 메소드 내 코드에 따라 달려 있다. Terminated가 설정될 경우 스레드는 끝나야 한다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====일시정지와 다시시작====&lt;br /&gt;
&lt;br /&gt;
TThread는 Suspend 메소드를 제공하긴 하지만 전혀 사용해선 안 된다! 반대로 Resume은 중단된 스레드를 다시 (안전하게) 시작하는 데에 사용할 수 있다. 하지만 Suspend를 사용해선 안 되므로 Resume 또한 무용지물이다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Suspend와 Resume을 사용해선 안 되는 이유는 설명하기 쉽다: Suspend는 당신에게 스레드의 중단 위치의 제어를 허용하지 않으므로 경합 조건(race condition)으로 이끌 수가 있어 위험하다. 임계영역(Critical section)에 진입해 다른 스레드들이 그 영역을 필요로 할 때 영역을 이용하지 못하도록 할 가능성이 크다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
따라서 POSIX 표준은 비협력적 방식으로 스레드를 일시정지하는 방도를 제공하지 않는다. 그 결과 어떤 유닉스 체제에서도 Suspend를 이용할 수 없다. 윈도우는 Suspend를 완전히 지원하지만 프로그램을 유닉스 플랫픔으로 변환하길 원할 경우 문제를 예방하려면 사용하지 말아야겠다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
보통은 Suspend를 사용하는 대신 스레드에 잠시 중지할 것을 알리기 위해 변수를 사용할 수 있다. 대상 스레드는 이 변수를 수시로 확인하고 필요 시 중단하여 변수가 다시 시작을 알릴 때까지 중단시킨다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====우선순위====&lt;br /&gt;
&lt;br /&gt;
스레드는 여러 우선순위를 가질 수 있다. 우선순위가 높은 스레드는 낮은 우선순위 작업보다 더 큰 시간 구획(time slice)을 얻어 실행할 가능성이 크다. 전형적인 예로, 단순한 계산만 실행하는 CPU-bound 스레드보다 I/O 연산에 우선순위가 높게 부여되는 사례를 들 수 있겠다. 대부분 I/O-bound 스레드는 입력이나 출력 연산이 완료되길 기다리기만 하며, CPU 용량(capacity)을 활용하는 경우가 드물다. 이러한 이유로 높은 우선순위를 허용할 수 있다. 이는 다음 I/O 연산에 빠르게 응답하고 준비할 수 있게 해준다. 우선순위가 높은 완전한 CPU-bound 스레드는 CPU 용량을 대부분 소모하여 다른 낮은 우선순위로 된 작업을 차단할 것이다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
일반적으로 다중 스레드를 사용하는 것은 의도대로 높은 속도의 혜택을 얻는 데 좋은 생각이다. 잘못된 결정은 성능에 매우 부정적인 영향을 미칠 수 있다. 심지어 노력만큼 향상된 것이 없는 우선순위를 테스트하거나 미세 조정하는 것이 엄청나게 까다로울지도 모른다.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;border: 1px solid black;&amp;quot;&lt;br /&gt;
|- style=&amp;quot;color: white; background-color: black;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;상수&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;설명&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;tpIdle&amp;#039;&amp;#039;&amp;#039;||다른 프로세스가 유휴 상태(idle)일 때만 스레드가 실행된다. &lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;tpLowest&amp;#039;&amp;#039;&amp;#039;||스레드가 가장 낮은 우선순위로 실행된다. &lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;tpLower&amp;#039;&amp;#039;&amp;#039;||스레드가 낮은 우선순위로 실행된다.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;tpNormal&amp;#039;&amp;#039;&amp;#039;||스레드가 보통 우선순위로 실행된다.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;tpHigher&amp;#039;&amp;#039;&amp;#039;||스레드가 높은 우선순위로 실행된다.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;tpHighest&amp;#039;&amp;#039;&amp;#039;||스레드가 가장 높은 우선순위로 실행된다.&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;tpTimeCritical&amp;#039;&amp;#039;&amp;#039;||스레드가 실시간 우선순위로 실행된다.&lt;br /&gt;
|- style=&amp;quot;color: black; background-color: gray;&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; |표 10.7: TThread.Priority에 가능한 값&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====동기화와 임계영역====&lt;br /&gt;
&lt;br /&gt;
동기화 메커니즘은 메인 스레드가 스레드 안전(thread-safe)하지 않은 라이브러리를 사용할지 모르는 여러 스레드들을 호출하도록 허용하기 위해 도입되었다. 이를 가능하게 하려면 메인 스레드가 이 코드를 실행할 때까지 스레드의 실행은 일시 정지된다. LCL은 대부분 GUI 라이브러리와 마찬가지로 스레드 안전(thread-safe)하지 않다. 따라서 모든 LCL 기반의 코드는 메인 스레드 또는 동기화 블록에 있어야 한다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
뮤텍스(Mutex)라고도 알려진 (상호배제) 임계 영역을 고려하는 것은 동기화 메커니즘을 설명하기 좋은 방법이다. 스레드를 임계 영역으로 진입시킬 때, 그 영역 내 다른 스레드가 이미 있을 경우 그것은 일시 정지된다. 이는 연산이 완료되고 다른 스레드가 동일한 임계 영역으로 진입하기 전에 결과를 이용할 수 있도록 보장한다. SyncObjs 유닛에 위치한 TCriticalSection 클래스는 두 개의 간단한 메소드, Enter 와 Leave를 제공한다. 첫 번째는 스레드가 임계 영역에 진입하고 있음을 나타내고, Leave 가 호출될 때까지 다른 작업이 들어가지 못하도록 막는다. 임계 영역으로 진입을 기다리는 스레드는 수면 상태(sleeping)에 있으며, 자신의 차례가 되면 운영체제가 자동으로 깨운다(wake).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
스레드는 운영체제가 작업 전환을 실행할 때 두 개의 기계어 명령 코드(machine code instruction) 사이에서 중단될 수 있다. 대부분 명령어는 하나 이상의 기계어 명령으로 구성되어 있기 때문에 이는 오브젝스 파스칼 명령어 중간에서 발생할 수도 있다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
MyVar 는 0값으로 시작할지도 모른다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
이제 첫 번째 스레드가 실행되기 시작한다. 이는 MyVar를 읽고 그에 4를 더한다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
이제 운영체제가 작업 전환을 한다. 두 번째 스레드는 모든 코드를 실행한다. 여전히 MyVar 는 0으로 읽은 후 4를 더한다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
이제 MyVar 는 4와 같아지고, 운영체제는 첫 번째 스레드로 다시 전환하는데 이 역시 MyVar에 4를 저장한다. 문제는 첫 번째 스레드가 정확히 그 지점에서 중단되지 않을 시 MyVar가 8이 될 수도 있다는 점이다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
두 개 이상의 스레드가 실행될 경우 문제가 더 심각해지며, 여느 타이밍 문제와 마찬가지로 무엇이 잘못되었는지 찾기가 매우 힘들다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
우리는 이 문제를 방지하기 위해 TCriticalSection을 이용해 이 영역을 다르게 코딩할 수 있다. 클래스는 짧고 이해가 쉽다:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
type&lt;br /&gt;
  TWaitResult = (wrSignaled, wrTimeout, wrAbandoned, wrError);&lt;br /&gt;
&lt;br /&gt;
  TSynchroObject = class(TObject)&lt;br /&gt;
    procedure Acquire; Virtual;&lt;br /&gt;
    procedure Release; Virtual;&lt;br /&gt;
  end;&lt;br /&gt;
&lt;br /&gt;
TCriticalSection = class(TSynchroObject)&lt;br /&gt;
  private&lt;br /&gt;
    CriticalSection: TRTLCriticalSection;&lt;br /&gt;
  public&lt;br /&gt;
    procedure   Acquire; Override;&lt;br /&gt;
    procedure   Release; Override;&lt;br /&gt;
    procedure   Enter;&lt;br /&gt;
    procedure   Leave;&lt;br /&gt;
    constructor Create;&lt;br /&gt;
    destructor  Destroy; Override;&lt;br /&gt;
  end;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
임계 영역은 일반적인 경합 조건(race condition) 문제와 관련이 있다. 경합 조건은 다중 스레드에 의해 실행되는 순서에 따라 다른 결과가 생산될지도 모르는 코드의 섹션을 의미한다. 이 시나리오는 오류가 발생하기 쉽고, 디버깅이 까다로운 것이 보통이다. 두 개의 스레드가 아래 코드를 실행한다고 가정하자.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
Local := MyVar;&lt;br /&gt;
Local := Local + 4;&lt;br /&gt;
MyVar := Local;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;border: 1px solid black;&amp;quot;&lt;br /&gt;
|- style=&amp;quot;color: white; background-color: black;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;시간&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;스레드 1&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;로컬 (스레드 1)&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;스레드 2&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;로컬 (스레드 2)&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;MyVar&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;1&amp;#039;&amp;#039;&amp;#039;||Local := MyVar;||0|| || ||0&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;2&amp;#039;&amp;#039;&amp;#039;||Local := Local + 4;||4|| || ||0&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;3&amp;#039;&amp;#039;&amp;#039;|| ||4||Local := MyVar;||0||0&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;4&amp;#039;&amp;#039;&amp;#039;|| ||4||Local := Local + 4;||4||0&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;5&amp;#039;&amp;#039;&amp;#039;|| ||4||MyVar := Local;||4||4&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;6&amp;#039;&amp;#039;&amp;#039;||MyVar:= Local;||4|| || ||4&lt;br /&gt;
|- style=&amp;quot;color: black; background-color: gray;&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;6&amp;quot; |표 10.8: 두 작업 간 경합 조건이 오류로 이끔&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
임계 영역은 전역적이어야 하며 접근하는 전역 변수에 특정적이어야 하는데, 여기서 MyVarCS 라고 부르는 정확한 이유이다. 코드를 실행하기 전에 TCriticalSection 클래스의 인스턴스를 생성함으로써 변수를 초기화해야 한다:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
MyVarCS.Enter;&lt;br /&gt;
try&lt;br /&gt;
  Local := MyVar;&lt;br /&gt;
  Local := Local + 4;&lt;br /&gt;
  MyVar := Local;&lt;br /&gt;
finally&lt;br /&gt;
  MyVarCS.Leave;&lt;br /&gt;
end;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
이러한 새 코드는 해당 코드 블록에 하나 이상의 스레드는 절대로 있을 수 없도록 해준다. try…finally 구문은 안전 조치로, 예외가 발생 시 다른 스레드들을 위해 임계 영역이 해제되도록 보장한다.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;border: 1px solid black;&amp;quot;&lt;br /&gt;
|- style=&amp;quot;color: white; background-color: black;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;시간&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;스레드 1&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;로컬 (스레드 1)&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;스레드 2&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;로컬 (스레드 2)&amp;#039;&amp;#039;&amp;#039;||&amp;#039;&amp;#039;&amp;#039;MyVar&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;1&amp;#039;&amp;#039;&amp;#039;||MyVarCS.Enter;||?|| || ||0&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;2&amp;#039;&amp;#039;&amp;#039;||Local := MyVar;||0|| || ||0&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;3&amp;#039;&amp;#039;&amp;#039;||Local := Local + 4;||4|| || ||0&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;4&amp;#039;&amp;#039;&amp;#039;|| ||4||MyVarCS.Enter;||?||0&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;5&amp;#039;&amp;#039;&amp;#039;||MyVar := Local;||4|| ||?||4&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;6&amp;#039;&amp;#039;&amp;#039;||MyVarCS.Leave;||4||?|| ||4&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;7&amp;#039;&amp;#039;&amp;#039;|| || ||Local := MyVar;||4||4&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;8&amp;#039;&amp;#039;&amp;#039;|| || ||Local := Local + 4;||8||4&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;9&amp;#039;&amp;#039;&amp;#039;|| || ||MyVar := Local;||8||8&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;10&amp;#039;&amp;#039;&amp;#039;|| || ||MyVarCS.Leave;||8||4&lt;br /&gt;
|- style=&amp;quot;color: black; background-color: gray;&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;6&amp;quot; |표 10.9: 같은 계산, 임계 영역으로 안정화됨&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
여기에 적절한 멀티스레딩을 이용한 완전하고 해석 가능한 애플리케이션 버전이 있다. 이 코드는 위의 예제와 동일하게 실행하며 항상 8에 해당하는 MyValue 값을 콘솔에 인쇄한다. 결과는 운영체제가 스레드를 실행하는 순서에 의존하지 않는다.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
program criticalsection;&lt;br /&gt;
{$apptype console}&lt;br /&gt;
{$mode objfpc}{$H+}&lt;br /&gt;
uses {$IFDEF UNIX}&lt;br /&gt;
       cthreads,&lt;br /&gt;
     {$ENDIF}&lt;br /&gt;
       Classes, SyncObjs;&lt;br /&gt;
&lt;br /&gt;
type TMyThread = class(TThread)&lt;br /&gt;
     public&lt;br /&gt;
       procedure Execute; override;&lt;br /&gt;
     end;&lt;br /&gt;
&lt;br /&gt;
var  MyVar  : Cardinal;&lt;br /&gt;
     MyVarCS: TCriticalSection;&lt;br /&gt;
     Thread1, Thread2: TMyThread;&lt;br /&gt;
&lt;br /&gt;
  procedure TMyThread.Execute; (* The procedure being executed with a Critical Section *)&lt;br /&gt;
    var Local: Cardinal;&lt;br /&gt;
  begin&lt;br /&gt;
    MyVarCS.Enter;&lt;br /&gt;
    try&lt;br /&gt;
      Local := MyVar;&lt;br /&gt;
      Local := Local + 4;&lt;br /&gt;
      MyVar := Local;&lt;br /&gt;
    finally&lt;br /&gt;
      MyVarCS.Leave;&lt;br /&gt;
    end;&lt;br /&gt;
  end;&lt;br /&gt;
&lt;br /&gt;
{ program criticalsection }&lt;br /&gt;
begin&lt;br /&gt;
  MyVar   := 0;                       (* Initializes MyVar           *)&lt;br /&gt;
  MyVarCS := TCriticalSection.Create; (* Creates the CriticalSection *)&lt;br /&gt;
  Thread1 := TMyThread.Create(False); (* Creates and        *)&lt;br /&gt;
  Thread2 := TMyThread.Create(False); (* starts the threads *)&lt;br /&gt;
  Thread1.WaitFor;                    (* Waits until the threads *)&lt;br /&gt;
  Thread2.WaitFor;                    (* finish executing        *)&lt;br /&gt;
  Thread1.Free;                       (* Release the threads ... *)&lt;br /&gt;
  Thread2.Free;&lt;br /&gt;
  MyVarCS.Free;                       (* ... and the critical section *)&lt;br /&gt;
  WriteLn(&amp;#039;MyVar = &amp;#039;, MyVar);         (* Show the result on screen    *)&lt;br /&gt;
end.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:LazarusCompleteGuide]]&lt;/div&gt;</summary>
		<author><name>Onionmixer</name></author>
	</entry>
</feed>