'Operations Dev'에 해당되는 글 19건

  1. 2010.12.11 종료
  2. 2010.12.11 생산자 / 소비자
  3. 2010.12.10 Producer / Customer
  4. 2010.12.10 자체 뮤텍스락 이용
  5. 2010.12.10 자체 스핀락 이용
  6. 2010.12.10 Concurrency
  7. 2010.12.10 식사하는 철학자
  8. 2010.12.10 Mutex
  9. 2010.12.10 Semaphore
  10. 2010.12.10 CriticalSection
posted by Kyleslab 2010. 12. 11. 01:39


이서비스는 쓰레드로 만들었습니다.
그리고 윈도우는 메인함수에서 메인쓰레드라는게 존재한다.
그리고 각각 동작한다.

그리고 아까이야기 했듯이 클래스단위로 쓰레드화 하는게 아니고
하나의 컨숨?한 쓰레드가 됩니다.
이 프로듀서를 어디서 생성을 할까요->메인에서 생성할겁니다.
끄려면 강제종료를 시켜야하는데 그러면 메인이 종료됩니다.
그러면서 자식쓰레드들도 종료가됩니다.

그럼 소멸자가 어디서 불릴까? ->메인스레드
서비스함수들은 어디서 돌아가고 있을까? -> 각각 자기스레드

그럼 소멸자가 호출되는 순간 그 스레드들은 돌고있을까 안돌고있을까?
-> 돌고있고 소멸자가 호출되도 돌리려고 시도 할 수 있다. -> 그러면 터진다

해결책
플래그변수를 불러요 -> Customer에 boolean변수 isEnd를 만든다
volatile -> 최적화 안하겠다 -> 캐싱하지 않겠다 ->멀티코어에서 발생할수있는 버그를 없애겠다
-> 메모리에 있는 변수 캐쉬에 올리지마. 느려도 걍 쓸테니
->컴파일러의 코드순서바꾸기도 방지

캐시 아이오 속도차이 를 극복하기위해 각각 자신이 사용하는 변수를 캐싱한다. 메모리의 복사본을
캐시메모리에 올린다. 하나의 메모리를 두개의 시피유에서 사용한다.

그리고 isEnd를 false로 세팅하고 각각의 소멸자에 true로 바꿔준다.
서비스는 isEnd가 Ture일때까지 돌도록 바꾼다

isend가 한번더 돌다가 종료할때

->>>>>>>>>> 하지만 그래도 터진다.

서로 스레드가 다르므로 생산자로 넘어갔을때 한번 실행하고 돌아간다.
이 미묘한 타이밍때문에 똑같이 터진다.

>>>>>>>>>>>>>>>>>> while루프를 빠져나와서 온순간까지 락걸어준다.

소멸자에서 wait코드가 있는거고 while루프 바깥에서 풀어주고
생성자는 리소스에 대해서 락걸고 while루프 바깥에서 풀어버리면 세이프한 코드가 된다.

. 저번주에 한 생산자/소비자 실습에서 프로그램 종료시에 에러가 날 수 있는 조건과 해결책에 대한 필기 문제
메인함수에서 프로듀서와 커스토머 쓰레드를 만들고
메인쓰레드가 종료될때 아직 이 두개의 쓰레드는 각자 자기 쓰레드에서 돌고 있는데, 메인쓰레드를 종료되면 터진다.
왜냐하면 메인쓰레드가 종료될때 소멸자가 호출되는데 이 호출되는 순간에도 각자 자신의 쓰레드가 돌고 있기 때문이다. 그러므로 메인쓰레드가 종료될때 소멸자가 호출되는것을 이용하여 소멸자가 호출되었을대
모든 자식 스레드를 종료해주기 위해 자신의 스레드가 종료되도록하게 한다. 그리고 그다음 메인스레드가 종료되게하면 문제가 해결된다.
::CloseHandle( ( HANDLE )( _threadHandle ) );

메인스레드가 종료될때 소멸자가 호출되는데
Thread::~Thread()
{
 ::WaitForSingleObject( ( HANDLE )( _threadHandle ), INFINITE); //반드시해주어야함 모든 자식 스레드를 종료해주기 위해 메인스레드가 종료하면 소멸자를 호출하게 되고 자신의 핸들스레드가 종료될때까지 기다리게 한다.!!!
 ::CloseHandle( ( HANDLE )( _threadHandle ) ); // 그다음에 메인 스레드를 종료한다.
}
내가 만든 스레드가 돌고 있는 상황에서 메인스레드가
종료 되버리면 에러가 난다.

메인스레드가 종료될때 클래스의 소멸자를 호출하게되면
소멸자에 지금 돌고있는 스레드가 모두 종료될때 까지 기다리게 한다.

스핀락을 사용하는 이유는 리소스를 사용? 대기? 하는 것이 컨텍스트스위칭이 일어나는것보다 빠르기 때문

'Operations Dev > Producer' 카테고리의 다른 글

Producer / Customer  (0) 2010.12.10
posted by Kyleslab 2010. 12. 11. 01:37

메인함수에서 소비자와 생산자의 쓰레드가 만들어지도록 호출하고
처리후 메인쓰레드가 종료될때 소멸자가 호출되는데 이 호출되는 순간에도 각자 자신의 쓰레드가 종료되지않고 돌고 있기 때문이다. 해결책은 메인쓰레드가 종료될때 소멸자가 호출되는것을 이용하여 소멸자가 호출되었을대 모든 자식 스레드를 종료할때까지 기다린다. 그다음 메인스레드가 종료되게하면 문제가 해결된다.

::WaitForSingleObject( ( HANDLE )( _thread ), INFINITE);

또한 이 생산자/소비자의 문제에서는 멀티코어에서 생길수 있는 동일 메모리공유 문제에 대해서는 volatile boolean변수로 플래그를 만들어 해결한다.

그러나 이경우에도 생산자와 소비자 서로의 쓰레드가 다르므로 터질가능성이 있다. 이경우에는 소멸자에서 웨이트를 넣어두고 와일루프안에서 이 웨이트를 풀어주게만든다.

::ReleaseMutex(_thread);

결국 플래그와 공유변수에 대한 락으로 해결하게된다.

posted by Kyleslab 2010. 12. 10. 23:45


Producer.h

#pragma once

#include <queue>
#include <string>

#include "Concurrency\Thread.h"
#include "Customer.h"
#include "Concurrency\Timer.h"
#include "Concurrency\SpinLock.h"

class Producer
{
public:
 Producer(float frequency);
 ~Producer();


public:
 void
  beginService();
 bool
  tryPop( std::string * product);
 
private:
 void service();

private:
 Thread * _thread;
 std::queue< std::string > _products;//경쟁관계에 있는 녀석
 Timer _timer;
 float _frequency;
 unsigned int _count;
 volatile bool _isEnd;
 SpinLock mylock;
};


Produce.cpp

#include "StdAfx.h"
#include "Producer.h"

#include <Windows.h>


Producer::Producer(float frequency)//인자를 갖지 않는 생성자를 호출한다 기입하지 않으면, 파라미터를 받는 생성자를 만들었다면 기본생성자는 호출되지않는다.
 : _count( 0 ),
 _isEnd(false),
 _frequency(frequency)
{
 
}

void Producer::beginService()
{
 _thread = new Thread( std::bind(&Producer::service, this));
}

Producer::~Producer(void)
{
 _isEnd = true;
 ::WaitForSingleObject( ( HANDLE )( _thread ), INFINITE); //반드시해주어야함 모든 자식 스레드를 종료해주기 위해 메인스레드가 종료하면 소멸자를
 delete _thread;

 // 메인스레드가 종료될때 소멸자 호출,. 그러나 지금 스레드가 작동중이라면???
 

}

bool Producer::tryPop( std::string * product)
{
 mylock.lock();
 bool result = false;

 if( !_products.empty())
 {
  *product = _products.front();
  _products.pop();
  result = true;
 }
 mylock.unlock();
 return result;

}

 

void Producer::service()

 _timer.start();
 
 while( !_isEnd )
 {
   
  if(_timer.elapsedSeconds() >= _frequency)
  {
   
   char number[100];
   itoa( _count, number, 10 );
   
   std::string product = "product";
   product += number;
   ++_count;
   _timer.stop();
   _timer.start();
   mylock.lock();
   _products.push( product );
   mylock.unlock();
  }
  
  ::Sleep(0); //원래는 블록큐로 가나, 0이니까 준비큐로가고 1초가 아닐때 다른작업할거있음 하라고 양보하는 것이다.
 }
 
}

Customer.h
#pragma once

#include "Concurrency\Thread.h"
#include "Concurrency\Timer.h"
#include "Concurrency\MutexLock.h"

class Producer;

class Customer
{
public:
 Customer( Producer * producer, // 포인터 타입으로 갖고 있게 한다. 인스턴스를 선언하지 않고, 클래스실체를 선언하지 않고 사용하는법
        float frequency);
 ~Customer();

public:
 void
  beginService();

private:
 void service();//백그라운드에서
 
 private:
 Thread * _thread;
 Producer * _producer;
 Timer _timer;
 float _frequency;
 volatile bool _isEnd;


};


Customer.cpp
#include "StdAfx.h"
#include <concrt.h>
#include <Windows.h>


#include "Customer.h"

 

#include "Producer.h"//헤더에서 그냥 선언만해놓고 여기서 추가해주면 사용할수 있다.


Customer::Customer( Producer * producer,
 float frequency)
 : _producer( producer ),
 _frequency( frequency ),
 _isEnd(false)
{

}


Customer::~Customer(void)
{
 _isEnd = true;
 ::WaitForSingleObject( ( HANDLE )( _thread ), INFINITE);
 delete _thread;
}


void Customer::beginService()
{
 _thread = new Thread( std::bind(&Customer::service, this));
}


void
 Customer::service()
{
 _timer.start();

 while( !_isEnd)
 {
  if(_timer.elapsedSeconds() >= _frequency )
  {
   std::string product;

   if( _producer->tryPop(&product)) // 커스토머 쓰레드 호출되는 곳의 쓰레드이다.
   {
 
    printf( "%s\n", product.c_str() );

    _timer.stop();
    _timer.start();
   }

  }
  ::Sleep( _frequency * 250 );
 }
}


ServiceThread.cpp
// ServiceThread.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"

#include<Windows.h>

#include "Customer.h"
#include "Producer.h"
int _tmain(int argc, _TCHAR* argv[])
{
 Producer p(0.01f);
 Customer c1( &p, 0.008);
 Customer c2( &p, 0.005 );

 p.beginService();
 ::Sleep( 2000 );
 c1.beginService();
 c2.beginService();

 Timer timer;
 timer.start();
 while( timer.elapsedSeconds() < 20);

 return 0;
}

 

'Operations Dev > Producer' 카테고리의 다른 글

종료  (0) 2010.12.11
posted by Kyleslab 2010. 12. 10. 22:09


// Test1.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

#include "Concurrency/Thread.h"
#include "Concurrency/MutexLock.h"

//이거 연결은 정적 라이브러리 연결 동적이 나올수도 있음

string g_buffer;
MutexLock g_lock; //1000번 찍는데 락을 걸어주기 위해서 우리가 만든 락 클래스를 이용한다.

int _tmain(int argc, _TCHAR* argv[])
{
 vector<Thread * >threads; //힙을 이용하면 new를 이용하면 생성하고 delete를 하면 우리가 생성 소멸 타이밍을 조절 할 수 있다.

 for(int i =0; i < 5; ++i)
 {
  char ch = 'a'+i;
  threads.push_back(new Thread( // 푸시백은 백터 맨뒤에 이것들을 추가하는것
  [ ch ]()->void //[]여기 안에는 클로져 특성을 가지는 변수, 캡쳐할 리스트들 ()인자값이 들어감
  {
   g_lock.lock();
   for(int i =0; i < 1000; ++i)
   {
    g_buffer +=ch;
   }
   g_lock.unlock(); //락을 걸어준다.

  }));
 }
 for_each(threads.begin(), //이것은 외우기
  threads.end(),
  [](Thread * thread)  //포위치로 쓰래드를 처음부터 끝까지 훌터서 지울려고 하는거임
 {
  delete thread; //벡터에는 포인터가 들어있기 때문에 벡터의 원소는 변화가 없다. 쓰레드가 종료 되면 지워버림
 });
   
 cout<<g_buffer<<endl;
 return 0;
}


 

'Operations Dev > Concurrency' 카테고리의 다른 글

자체 스핀락 이용  (0) 2010.12.10
Concurrency  (0) 2010.12.10
posted by Kyleslab 2010. 12. 10. 22:08


// Test.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

#include "Concurrency/Thread.h"
#include "Concurrency/SpinLock.h"

//이거 연결은 정적 라이브러리 연결 동적이 나올수도 있음

string g_buffer;
SpinLock g_lock; //1000번 찍는데 락을 걸어주기 위해서 우리가 만든 락 클래스를 이용한다.

int _tmain(int argc, _TCHAR* argv[])
{
 vector<Thread * >threads; //힙을 이용하면 new를 이용하면 생성하고 delete를 하면 우리가 생성 소멸 타이밍을 조절 할 수 있다.

 for(int i =0; i < 5; ++i)
 {
  char ch = 'a'+i;
  threads.push_back(new Thread( // 푸시백은 백터 맨뒤에 이것들을 추가하는것
  [ ch ]()->void //[]여기 안에는 클로져 특성을 가지는 변수, 캡쳐할 리스트들 ()인자값이 들어감
  {
   g_lock.lock();
   for(int i =0; i < 1000; ++i)
   {
    g_buffer +=ch;
   }
   g_lock.unlock(); //락을 걸어준다.

  }));
 }
 for_each(threads.begin(), //이것은 외우기
  threads.end(),
  [](Thread * thread)  //포위치로 쓰래드를 처음부터 끝까지 훌터서 지울려고 하는거임
 {
  delete thread; //벡터에는 포인터가 들어있기 때문에 벡터의 원소는 변화가 없다. 쓰레드가 종료 되면 지워버림
 });
   
 cout<<g_buffer<<endl;
 return 0;
}

 

'Operations Dev > Concurrency' 카테고리의 다른 글

자체 뮤텍스락 이용  (0) 2010.12.10
Concurrency  (0) 2010.12.10
posted by Kyleslab 2010. 12. 10. 22:07

-----Thread.h
#pragma once

#include <functional>

//Rari? 리소스를 얻으면 바로 초기화한다.보통 윈도 api를 사용한다. 독립적으로 되려면 매기기 마다 컴파일해야한다. ios로 가면 ios api를 써야한다.

class Thread
{
public:
 Thread( std::function< void () > const & threadFunc );//스레드를 만들 함수를 넘기다. 리턴타입없고 인자도없다.
 ~Thread();

public:
 unsigned int
  getThreadId() const;
 unsigned int
  getThreadHandle() const;

private:
 Thread( Thread const & value ){}
 Thread & operator=( Thread const & value){ return *this;}

private:
 unsigned int _threadId;
 unsigned int _threadHandle;
 std::function< void () > _threadFunc; // 터지는 것을 방지 하고 위해서 쓰레드의 생명주기를 클래스와 같게 한다.

};

---Thread.cpp
//#ifdef _WIN32 //플랫폼 독립적인 녀석을 만들때

#include "stdafx.h"

#include "Thread.h"

#include <Windows.h>
#include <process.h>

static unsigned int __stdcall ThreadEntryPoint ( void * arg ) // static외부에서 절대 접근불가함수 이파일안에서만 동작 윈도우 스레드로 만들어져서 넘길수있다.
{
 (* ( std::function< void () >* )( arg ))();

 return 0;

}


Thread::Thread( std::function< void () > const & threadFunc )
 :_threadFunc( threadFunc )
{
 //우리가 만들고 싶은 것은 threadFunc 스레드인데 비긴스레드는 불가능 하다. 스레드엔트리포인트는 비긴스레드가 가능하니까 스레드펀크함수를 변수로 해서 전달한다.
 _threadHandle = ::_beginthreadex( NULL, 
      0,
      ThreadEntryPoint,
      ( void *)( &_threadFunc ), // 없어진것을 호출하면 터진다.
      0,
      &_threadId);
}

Thread::~Thread()
{
 ::WaitForSingleObject( ( HANDLE )( _threadHandle ), INFINITE); //반드시해주어야함 모든 자식 스레드를 종료해주기 위해 메인스레드가 종료하면 소멸자를 호출하게 되고 자신의 핸들스레드가 종료될때까지 기다리게 한다.!!!
 ::CloseHandle( ( HANDLE )( _threadHandle ) ); // 그다음에 메인 스레드를 종료한다.
}

unsigned int
 Thread::getThreadId() const
{
 return _threadId;
}

unsigned int
 Thread::getThreadHandle() const
{
 return _threadHandle;
}

---SpinLock.h
#pragma once

#include <Windows.h>
class SpinLock
{
public:
 SpinLock();
 ~SpinLock();

public:
 void lock();
 void unlock();

private:
 SpinLock(SpinLock const & value){}
 SpinLock &operator = (SpinLock const & rhs){return * this;}

private:
 ::CRITICAL_SECTION _lock;
};

-- SpinLock.cpp
#include "stdafx.h"

#include "SpinLock.h"

SpinLock::SpinLock()
{
 ::InitializeCriticalSection(&_lock); //객체 생성
}

SpinLock::~SpinLock()
{
 ::DeleteCriticalSection(&_lock); //해제
}

void SpinLock::lock()
{
 ::EnterCriticalSection(&_lock);
}

void SpinLock::unlock()
{
 ::LeaveCriticalSection(&_lock);
}

--Mutex.h
#pragma once

#include <Windows.h>
class MutexLock
{
public:
 MutexLock();
 ~MutexLock();

public:
 void lock();
 void unlock();

private:
 MutexLock(MutexLock const & value){}
 MutexLock &operator = (MutexLock const & rhs){return * this;}

private:
 HANDLE _lock;
};

--Mutex.cpp
#include "stdafx.h"

#include "MutexLock.h"

MutexLock::MutexLock()
{
  _lock = ::CreateMutexA(NULL, FALSE, NULL);//객체 생성
}

MutexLock::~MutexLock()
{
  ::CloseHandle(_lock); //해제
}

void MutexLock::lock()
{
 ::WaitForSingleObject(_lock, INFINITE);
}

void MutexLock::unlock()
{
 ::ReleaseMutex(_lock);
}

'Operations Dev > Concurrency' 카테고리의 다른 글

자체 뮤텍스락 이용  (0) 2010.12.10
자체 스핀락 이용  (0) 2010.12.10
posted by Kyleslab 2010. 12. 10. 21:22

// Chapter06.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <string>

#include <windows.h>
#include <process.h>

#include <iostream>
using namespace std;

int const MAX_FORK = 5;
int const MAX_PHILOSOPHER = 5;
HANDLE g_forks[ MAX_FORK ];
HANDLE g_room;


void eat( string const & philosopher );
void think( string const & philosopher );
unsigned int WINAPI startDinner( LPVOID param );

int _tmain(int argc, _TCHAR* argv[])
{
 string philo[MAX_PHILOSOPHER] = {"Socrates", "Plato", "Fredeu", "Kant", "Kongja"};
 DWORD threadIDs[MAX_PHILOSOPHER];
 HANDLE threadHandles[ MAX_PHILOSOPHER ];

 for( int i = 0; i < MAX_FORK; ++i )
 {

  g_forks[ i ] = ::CreateSemaphore( NULL, 1, 1, NULL );

 }
 g_room = ::CreateSemaphore( NULL, 4, 4, NULL );

 for(int i =0; i<MAX_PHILOSOPHER; ++i)
 {
  threadHandles[i] = (HANDLE) ::_beginthreadex( NULL, 0 , startDinner,(LPVOID*)(&philo[i]),0,(unsigned int *)&threadIDs[i]);
 }

 DWORD result = ::WaitForMultipleObjects(MAX_PHILOSOPHER, &threadHandles[0],TRUE,INFINITE);
 if(result == WAIT_OBJECT_0)
 {

 }

 for( int i = 0; i < MAX_FORK; ++i )
 {

  ::ReleaseSemaphore(g_forks[i],1,NULL);

 }
 ::ReleaseSemaphore(g_room,1,NULL);


 for(int i = 0; i< MAX_PHILOSOPHER; ++i)
 {
  CloseHandle(threadHandles[i]);
  CloseHandle(g_forks[i]);
 }
 CloseHandle(g_room);


 return 0;
}


void eat( string const & philosopher )
{

 ::Sleep( 100 );
 cout << philosopher+" eat something.\n";
 //printf("%s eat something.\n",philosopher);
}

void think( string const & philosopher )
{

 ::Sleep( 100 );
 cout << philosopher+" think something.\n";
 //printf("%s think something.\n",philosopher);

}

unsigned int WINAPI startDinner( LPVOID param )
{
 string ch = *((string *)param);
 for(int i =0 ; i< MAX_FORK ; i++)
 {

  think(ch);
  DWORD result = ::WaitForSingleObject(g_room,INFINITE);
  DWORD result2 = ::WaitForSingleObject(g_forks[i],INFINITE);
  result2 = ::WaitForSingleObject(g_forks[i+1%5],INFINITE);

  eat(ch);
  ::ReleaseSemaphore(g_forks[i+1%5],1,NULL);
  ::ReleaseSemaphore(g_forks[i],1,NULL);
  ::ReleaseSemaphore(g_room,1,NULL);
 }

 return 0;
}

posted by Kyleslab 2010. 12. 10. 18:24


// Example02_Mutex.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"

#include "Windows.h"
#include <process.h>

//#include <concrt.h>

#include <string>
#include <iostream>
using namespace std;

unsigned int WINAPI writeCharacter( LPVOID param);

string g_string;
int const MAX_THREAD = 5;
HANDLE g_mutexHandle;

int _tmain(int argc, _TCHAR* argv[])
{
 //가용 공간을 미리 예약해 놓는 부분,
 //g_string.reserve( MAX_THREAD * 1000 +1 );

 g_mutexHandle = ::CreateMutexA( NULL, FALSE, NULL);

 //char ch = 'a';
 DWORD threadIDs[MAX_THREAD];
 HANDLE threadHandles[MAX_THREAD];
 char alphas[MAX_THREAD];

 for(int i=0; i < MAX_THREAD; ++i)
 {
  alphas[i] = 'a' + i;
  threadHandles[i] = (HANDLE)::_beginthreadex( NULL,
   0,
   writeCharacter,
   (LPVOID*)(&alphas[i]), // LPVOID 포인터 타입 무슨 타입인지알아야한다. 이것은 char타입니다.
   0,
   (unsigned int *)&threadIDs[i]);

 }

 DWORD result =
  ::WaitForMultipleObjects(MAX_THREAD,
  &threadHandles[0],
  TRUE,
  INFINITE);

 //결과값이 제대로 나온다면
 if(result == WAIT_OBJECT_0)
 {
  cout<<g_string;
 }

 //::ReleaseMutex(g_mutexHandle);

 for(int i=0; i < MAX_THREAD; ++i)
 {
  CloseHandle(threadHandles[i]);
 }
 CloseHandle( g_mutexHandle);
 return 0;
}

unsigned int WINAPI writeCharacter(LPVOID param)
{
 char ch = *((char*)param);

 DWORD result = ::WaitForSingleObject(g_mutexHandle,INFINITE); // 대기시간 무한!

 for(int i = 0; i < 1000; ++i)
 {
  g_string += ch;
 }

 ::ReleaseMutex(g_mutexHandle);

 return 0;
}

'Operations Dev > writech' 카테고리의 다른 글

Semaphore  (0) 2010.12.10
CriticalSection  (0) 2010.12.10
SpinLock  (0) 2010.12.10
SpinLock2  (0) 2010.12.10
SimpleConcurrency  (0) 2010.12.10
posted by Kyleslab 2010. 12. 10. 18:23

// Example03_Semaphore.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"

#include<windows.h>
#include<process.h>

#include<string>
#include<iostream>
using namespace std;

unsigned int WINAPI writeCharacter(LPVOID param);

string g_string;
int const MAX_THREAD = 5;
HANDLE g_semaphoreHandle;

int _tmain(int argc, _TCHAR* argv[])
{
 g_semaphoreHandle = ::CreateSemaphore(NULL,1, 1 , NULL);
 g_string.reserve(MAX_THREAD * 1000 +1);  //가용공간 예약부분

 DWORD threadIDs[MAX_THREAD];
 HANDLE threadHandles[MAX_THREAD];
 char alphas[MAX_THREAD];

 for(int i =0; i<MAX_THREAD; ++i)
 {
  alphas[i] = 'a' + i;

  threadHandles[i] = (HANDLE) ::_beginthreadex( NULL, 0 , writeCharacter,(LPVOID*)(&alphas[i]),0,(unsigned int *)&threadIDs[i]);
 }
 
 DWORD result = ::WaitForMultipleObjects(MAX_THREAD, &threadHandles[0],TRUE,INFINITE);
 if(result == WAIT_OBJECT_0)
 {
  
  cout<<g_string;
  
 }

 for(int i = 0; i< MAX_THREAD; ++i)
 {
  CloseHandle(threadHandles[i]);
 }
 CloseHandle(g_semaphoreHandle);

 return 0;
}

unsigned int WINAPI writeCharacter(LPVOID param)
{
 char ch = *((char *)param);
 DWORD result = ::WaitForSingleObject(g_semaphoreHandle,INFINITE);
 for(int i = 0; i< 1000; ++i)
 {
  g_string += ch;
 }
 ::ReleaseSemaphore(g_semaphoreHandle,1,NULL);
 
 return 0;
}


 

'Operations Dev > writech' 카테고리의 다른 글

Mutex  (0) 2010.12.10
CriticalSection  (0) 2010.12.10
SpinLock  (0) 2010.12.10
SpinLock2  (0) 2010.12.10
SimpleConcurrency  (0) 2010.12.10
posted by Kyleslab 2010. 12. 10. 18:22

// Example04_CriticalSection.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
// CriticalSection은 유저모드(재귀 스핀락)인데 오늘은 일반 락

#include "stdafx.h"

#include<windows.h>
#include<process.h>

#include<string>
#include<iostream>
using namespace std;

unsigned int WINAPI writeCharacter(LPVOID param);

string g_string;
int const MAX_THREAD = 5;
CRITICAL_SECTION  g_criticalSection;

int _tmain(int argc, _TCHAR* argv[])
{
 ::InitializeCriticalSection(&g_criticalSection);

 DWORD threadIDs[MAX_THREAD];
 HANDLE threadHandles[MAX_THREAD];
 char alphas[MAX_THREAD];

 for(int i =0; i<MAX_THREAD; ++i)
 {
  alphas[i] = 'a' + i;

  threadHandles[i] = (HANDLE) ::_beginthreadex( NULL, 0 , writeCharacter,(LPVOID*)(&alphas[i]),0,(unsigned int *)&threadIDs[i]);
 }
 
 DWORD result = ::WaitForMultipleObjects(MAX_THREAD, &threadHandles[0],TRUE,INFINITE);
 if(result == WAIT_OBJECT_0)
 {
  
  cout<<g_string;
  
 }
 for(int i = 0; i< MAX_THREAD; ++i)
 {
  CloseHandle(threadHandles[i]);
 }
 ::DeleteCriticalSection(&g_criticalSection);

 return 0;
}

unsigned int WINAPI writeCharacter(LPVOID param)
{
 char ch = *((char *)param);
 ::EnterCriticalSection(&g_criticalSection);
 /***************임계영역 *************************/
 for(int i = 0; i< 1000; ++i)
 {
  g_string += ch;
 }
 /**************************************************/
 ::LeaveCriticalSection(&g_criticalSection);
 
 return 0;
}

'Operations Dev > writech' 카테고리의 다른 글

Mutex  (0) 2010.12.10
Semaphore  (0) 2010.12.10
SpinLock  (0) 2010.12.10
SpinLock2  (0) 2010.12.10
SimpleConcurrency  (0) 2010.12.10