목차
//
org : http://msdn.microsoft.com/en-us/library/ms810428
Table 1. Synchronization Objects Summary
Name | Relative speed | Cross process | Resource counting | Supported platforms |
Critical Section | Fast | No | No (Exclusive Access) | 95/NT/CE |
Mutex | Slow | Yes | No (Exclusive Access) | 95/NT/CE |
Semaphore | Slow | Yes | Yes | 95/NT |
Event | Slow | Yes | Yes* | 95/NT/CE |
Metered Section | Fast | Yes | Yes | 95/NT/CE |
* Events can be used for resource counting, but they do not keep track of the count for you.
//
org : http://tiger5net.egloos.com/5537603
object | Linux/Unix | Windows |
File Lock | kernel-mode | kernel-mode |
† Critical Section | 없음 | user-mode 한 프로세스 내에서만 사용가능 |
Interlock | 없음 | user-mode 한 프로세스 내에서만 사용가능 |
† Mutex | POSIX 함수 한 프로세스 내에서만 사용가능 하나의 공유자원 동기화에 사용 | kernel-mode 프로세스끼리도 사용가능 타임아웃기능 사용가능 하나의 공유자원 동기화에 사용 |
† Semaphore | kernel-mode POSIX 함수 프로세스끼리도 사용가능 다중 공유자원 동기화에 사용 | kernel-mode 프로세스끼리도 사용가능 타임아웃기능 사용가능 다중 공유자원 동기화에 사용 |
Condition Variable | POSIX 함수 타임아웃기능 사용가능 다중 스레드를 동시에 깨울 수 있음 | 없음 |
† Event | 없음 | kernel-mode 프로세스끼리도 사용가능 타임아웃기능 사용가능 다중 스레드나 프로세스를 동시에 깨울 수 있음 |
//
-
동기화(Syncronazation)#
http://en.wikipedia.org/wiki/Synchronization
- 멀티프로그래밍(두개 이상의 쓰레드가 같은
데이터를 공유하며 실행되고 있을때)에서
에러(충돌,교착)가 발생하지 않고 조화롭게 실행되도록 하는 일련의 작업
-
이용되는 이론 : 세마포어(Semaphore), 임계구역(Critical Section), 스핀락(SpinLock), 상호배제(Mutual
Exclusion, Mutex), 이벤트, Metered Section
-
세마포어 (Semaphore) #
http://ko.wikipedia.org/wiki/%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4
-
멀티프로그래밍에서 공유자원에 대한 동시 접근을 제한하는 방법
- 세마포어 S는 정수값을 가지는 변수이며, 다음과 같이
P(test--)와 V(increment++)라는 명령에 의해서만 접근할 수 있다.
P는 임계 구역에 들어가기 전에
수행되고, V는 임계 구역에서 나올 때 수행된다
- 세마포어는 임계구역을 다루기 위한 커널 객체다.(0이상의 정수)
CreateSemaphore : 세마포어 생성
ReleaseSemaphore : 세마포어 카운트 증가
WaitForMultipleObjects : 세마포어 시그널을 기다림
공유자원(임계구역)에 대한 접근을 하면 세마포어 카운트
감소
- 상태 : wait/ capture/ release
- 카운트
- 감소 : capture, 공유자원에 접근시
- 증가 : release, ReleaseSemaphore()함수
호출시
- 0 : wait, 이면 공유자원에 대한 접근이 거부되지 않는다.
- 동작 : 세마포어
카운트가 증가(ReleaseSemaphore)하면,
wait에 시그널이 가고(WaitForMultipleObjects), -
임계구역 안에 위치
공유자원(임계구역[EnterCriticalSection()-LeaveCriticalSection())의
사용이 허용되면서
세마포어 카운트 감소
-
임계 구역( Critical section )#
http://ko.wikipedia.org/wiki/%EC%9E%84%EA%B3%84_%EA%B5%AC%EC%97%AD
-
동시 프로그래밍에서 공유 불가능한 자원의 동시 사용을 피하기 위해 사용되는 알고리즘
동시에 둘 이상의 스레드가 동시에 접근해서는 안되는
공유 자원(자료 구조 또는 장치)을 접근하는 코드의 일부를 말한다.
임계 구역은 주로 지정된 시간이 지난 후 사라진다. 그래서 어떤
스레드(작업 또는 프로세스)가 임계 구역에 들어가려면 지정된 시간을 기다려야 한다.
세마포어와 같이, 배타적인 사용을 보장하기 위해서는
임계영역의 입장과 퇴장에는 어떤 동기화 기작이 필요하다.
- InitializeCriticalSection : 임계구역
초기화
- DeleteCriticalSection : 임계구역 삭제
- EnterCriticalSection :
임계구역 진입, Lock
- LeaveCriticalSection : 임계구역 떠남, Release
-
스핀락(SpinLock)#
임계구역에 진입이 불가능할때 잠시 루프를 돌면서 재시도 하는 것(스핀)
- 커널프로그래밍에서는 특히 가능한한 짧은 시간내에
처리를 완료해야한다. MS 에서는 처리시간을 25마이크로초 이하로 하도록 권장한다.
크리티컬 섹션에 진입하기 전에 커널은 보호된 DPC
큐와 관련된 스핀락을 획득해야 한다.
스핀락 획득에 실 패하면 성공할 때까지 계속 시도한다.
스핀락이란 이름은 락을 획득할 때까지
커널(즉, 프로세스)는 계속해서 빙빙 돌고 있다(spinning)는데서 왔다.
-
Metered Section#
다른 동기화 객체들 보다 100배정도 빠르고(임계구역보다는 50배) 다른 프로세스 간에도 사용
가능
http://msdn.microsoft.com/en-us/library/ms810428.aspx
-
참고사이트#
- Thread Synchronization for Beginners
https://secure.codeproject.com/KB/threads/Synchronization.aspx?display=Print - Introduction to Multi-threaded Code
http://www.codeproject.com/KB/threads/sync.aspx?display=Print
- Thread Synchronization for Beginners
-
소스#
- #include<windows.h>
#include <stdio.h>
#include<iostream>
#include <process.h>
#include "MeteredSection.h"
using namespace std;
const int LOOP_COUNT=10000;
//============================================================================
/*
Thread Synchronization for Beginners
https://secure.codeproject.com/KB/threads/Synchronization.aspx?display=Print
*/
//============================================================================
// Declare the global variable
static int g_n;
CRITICAL_SECTION m_cs;
////////Thread One Function///////////////////
UINT ThreadOne(LPVOID lParam)
{
// Lock the Critical section
EnterCriticalSection(&m_cs);
for(int i=0;i<10;i++)
{
g_n++;
cout << "Thread 1: " << g_n << "\n";
}
//Release the Critical section
LeaveCriticalSection(&m_cs);
// return the thread
return 0;
}
////////Thread Two Function///////////////////
UINT ThreadTwo(LPVOID lParam)
{
// Lock the Critical section
EnterCriticalSection(&m_cs);
for(int i=0;i<10;i++)
{
g_n++;
cout << "Thread 2: "<< g_n << "\n";
}
//Release the Critical section
LeaveCriticalSection(&m_cs);
// return the thread
return 0;
}
int main_CriticalSection0()
{
// Create the array of Handle
HANDLE hThrd[2];
//Thread ID's
DWORD IDThread1, IDThread2;
//Initilize the critical section
InitializeCriticalSection(&m_cs);
// Create thredas use CreateThread function with NULL Security
hThrd[0] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) ThreadOne,(LPVOID)NULL,0,&IDThread1);
hThrd[1] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) ThreadTwo,(LPVOID)NULL,0,&IDThread2);
// Wait for the main thread
WaitForMultipleObjects(2,hThrd,TRUE,INFINITE);
// Delete critical Section
DeleteCriticalSection(&m_cs);
return 0;
}
//============================================================================
//============================================================================
/*
Introduction to Multi-threaded Code
http://www.codeproject.com/KB/threads/sync.aspx?display=Print
*/
//============================================================================
//No Synchronization
//#include <process.h>
//#include <stdio.h>
int a[ 5 ];
void Thread_NS( void* pParams )
{
int i, num = 0;
int cnt=0;
while ( 1 )
{
for ( i = 0; i < 5; i++ ) a[ i ] = num;
num++;
}
}
int main_NoSynchronization( void )
{
_beginthread( Thread_NS, 0, NULL );
int cnt=0;
while ( cnt++ <LOOP_COUNT )
{
printf("%d-%d %d %d %d %d\n", cnt,a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], a[ 4 ] );
//Sleep(500);
}
return 0;
}
//============================================================================
//Critical Section Objects
CRITICAL_SECTION cs;
// int a[ 5 ];
void Thread_CS( void* pParams )
{
int i, num = 0;
int cnt=0;
while ( 1 )
{
EnterCriticalSection( &cs );
for ( i = 0; i < 5; i++ ) a[ i ] = num;
LeaveCriticalSection( &cs );
num++;
}
}
int main_CriticalSection( void )
{
InitializeCriticalSection( &cs );
_beginthread( Thread_CS, 0, NULL );
int cnt=0;
while ( cnt++ <LOOP_COUNT )
{
EnterCriticalSection( &cs );
printf( "%d-%d %d %d %d %d\n", cnt,a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], a[ 4 ] );
LeaveCriticalSection( &cs );
}
return 0;
}
//============================================================================
//Mutex
//#include <windows.h>
//#include <process.h>
//#include <stdio.h>
HANDLE hMutex;
//int a[ 5 ];
void Thread_Mutex( void* pParams )
{
int i, num = 0;
while ( TRUE )
{
WaitForSingleObject( hMutex, INFINITE );
for ( i = 0; i < 5; i++ ) a[ i ] = num;
ReleaseMutex( hMutex );
num++;
}
}
int main_Mutex( void )
{
hMutex = CreateMutex( NULL, FALSE, NULL );
_beginthread( Thread_Mutex, 0, NULL );
int cnt=0;
while ( cnt++ <LOOP_COUNT )
{
WaitForSingleObject( hMutex, INFINITE );
printf( "%d-%d %d %d %d %d\n", cnt, a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], a[ 4 ] );
ReleaseMutex( hMutex );
}
return 0;
}
//============================================================================
// Event
//#include <windows.h>
//#include <process.h>
//#include <stdio.h>
HANDLE hEvent1, hEvent2;
//int a[ 5 ];
void Thread_Event( void* pParams )
{
int i, num = 0;
while ( TRUE )
{
WaitForSingleObject( hEvent2, INFINITE );
for ( i = 0; i < 5; i++ ) a[ i ] = num;
SetEvent( hEvent1 );
num++;
}
}
int main_Event( void )
{
hEvent1 = CreateEvent( NULL, FALSE, TRUE, NULL );
hEvent2 = CreateEvent( NULL, FALSE, FALSE, NULL );
_beginthread( Thread_Event, 0, NULL );
int cnt=0;
while ( cnt++ <LOOP_COUNT )
{
WaitForSingleObject( hEvent1, INFINITE );
printf( "%d %d %d %d %d\n",
a[ 0 ], a[ 1 ], a[ 2 ],
a[ 3 ], a[ 4 ] );
SetEvent( hEvent2 );
}
return 0;
}
//============================================================================
//============================================================================
//Critical Section witn Semaphore
//Critical Section을 닫는다면 이것을 사용하는 쓰레드도 종료시켜야 한다.
//CRITICAL_SECTION cs;
// int a[ 5 ];
HANDLE hSmp;
void Thread_CS_Semaphore( void* pParams )
{
int i, num = 0;
int cnt=0;
while ( 1 )
{
EnterCriticalSection( &cs );
WaitForSingleObject( hSmp, INFINITE );
for ( i = 0; i < 5; i++ ) a[ i ] = num;
LeaveCriticalSection( &cs );
num++;
}
}
/*
// CRITICAL_SECTION
typedef struct _RTL_CRITICAL_SECTION {
PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
LONG LockCount;
LONG RecursionCount;
HANDLE OwningThread; // from the thread's ClientId->UniqueThread
HANDLE LockSemaphore;
ULONG_PTR SpinCount; // force size on 64-bit systems when packed
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
윈도우 에서 제공하는 동기화 함수들은 내부적으로 세마포어와 스핀락 알고리즘 구현해서 사용하고 있다.
*/
int main_CriticalSection_Semaphore( void )
{
/*
//현재 문제
몇번 루프를 돌고 더이상 실행이 되지 않는다.
세마포어 카운트 최대치를 넘으면 ReleaseSemaphore()가 FLASE 리턴
최소치와 최대치를 둘다 1000으로 맞추면 실행 10000번까지는 성공
*/
hSmp = ::CreateSemaphore(NULL, // no security attributes
5, // initial count
10, // max count, 세마포어 Object(큐)의 최대치,
NULL); // anonymous
InitializeCriticalSection( &cs );
//_beginthread( Thread_CS_Semaphore, 0, NULL );
HANDLE hThrd = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) Thread_CS_Semaphore,(LPVOID)NULL,0,0);
BOOL result;
long PreCount=0;
int cnt=0;
while ( cnt++ <LOOP_COUNT )
{
EnterCriticalSection( &cs );
result= ReleaseSemaphore(hSmp, 1, &PreCount );
if(!result){
printf( "ERROR-(%d,%d)-%d %d %d %d %d\n", cnt,PreCount,a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], a[ 4 ] );
//break;
}else{
printf( "(%d,%d)-%d %d %d %d %d\n", cnt,PreCount,a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], a[ 4 ] );
}
LeaveCriticalSection( &cs );
}
//핸들 정리 전에 쓰레드를 종료 시켜야 한다.
TerminateThread(hThrd,0);
//핸들 정리
::CloseHandle(hSmp);
::DeleteCriticalSection(&cs);
return 0;
}
//============================================================================
//============================================================================
//Metered Section
//Metered Section을 닫을때(CloseMeteredSection()) 이것을 사용하는 쓰레드를 먼저 종료시켜야 한다.
//CRITICAL_SECTION cs;
// int a[ 5 ];
METERED_SECTION *pms=0;
long lMsCount=0;
BOOL bContinue=1;
void Thread_MeteredSection( void* pParams )
{
int i, num = 0;
DWORD ret=0;
int cnt=0;
bContinue=TRUE;
while ( bContinue )
{
EnterMeteredSection( pms,0 );
for ( i = 0; i < 5; i++ ) a[ i ] = num;
LeaveMeteredSection( pms, 1, &lMsCount );
num++;
}
}
int main_MeteredSection( void )
{
pms = CreateMeteredSection( 100, 100, NULL );
//_beginthread( Thread_MeteredSection, 0, NULL );
DWORD IDThread1=0;
HANDLE hThrd = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) Thread_MeteredSection,(LPVOID)NULL,0,&IDThread1);
// CreateThread, ExitThread, TerminateThread
int cnt=0;
while ( cnt++ <LOOP_COUNT )
{
EnterMeteredSection( pms,0 );//MS Count 감소
printf( "(%d,%d) -%d %d %d %d %d\n", cnt,lMsCount,a[ 0 ], a[ 1 ], a[ 2 ], a[ 3 ], a[ 4 ] );
LeaveMeteredSection( pms, 1, &lMsCount);//MS Count 증가
}
//TerminateThread(hThrd,0);
bContinue=FALSE;
CloseMeteredSection(pms);//쓰레드를 닫는 후에 호출
return 0;
}
//============================================================================
//============================================================================
int main()
{
//main_CriticalSection0();
//main_NoSynchronization();//51,424,706
//main_CriticalSection(); //20000, 19947,21391
//main_Mutex();//10000, 10050
//main_Event();//10000
//main_CriticalSection_Semaphore();//진행 않됨, 문제 있음
main_MeteredSection();//4,185,518, 속도가 100배, Process간에도 가능
cin.get();
return 0;
}
'Code' 카테고리의 다른 글
APM 설치 (0) | 2012.08.11 |
---|---|
Memory Mapped File (0) | 2012.08.01 |
Quake 3 source build (0) | 2008.11.18 |
filemon , regmon source (0) | 2008.11.08 |
[vb6] Visual Basic 6에서 마우스 휠 사용하기 (0) | 2008.11.05 |