본문 바로가기

프로그램언어/boost

[ Boost ] Boost::thread #3

Boost 목록
 

링크 : http://tingcobell.tistory.com/295


이번에 이야기 하고 싶은 내용은 thread 중 데이터 관리에 대한 내용을 이야기 해볼까 합니다.

보편적으로 multi-thread에 대한 내용을 검색 또는 기본적으로 어디서 들어본 내용이 있을 수 있습니다.

하지만 여기서 다루고 싶은 내용은 mutex 즉, lock에 대한 이야기를 꺼내보려고 합니다.

가량 어떠한 중요한 공유하고 있는 데이터가 있다고 생각하겠습니다.

그런데 thread의 경합에 의해서 원하던 원하지 않던 예상결과가 틀리게 나오는 것을 쉽게 접할 수 있습니다.

대충 여기저기 내용을 검색을 통해서 알것이라는 전재를 통해 정리합니다.

 


위 UML에서 보여주고 있는 Manager는 무엇을 하는 놈일까요? 여기서 말씀드리고 싶은 내용은 데이터 공유에

대한 것임을 말하고 싶습니다. 아래 그림 클라이언트 3개 다시 말해 스레드가 3개인 경우에 각각의 클라이언트의

경합에 대한 조건이 있어야 된다는 것입니다. 이 클라이언트의 공용된 데이터를 조작을 하게 될 때, 데이터가 

잘못되지 않도록 조율이 필요하다는 것입니다.

테스트 소스

#include <boost/thread/thread.hpp>

#include <boost/thread/mutex.hpp>

#include <vector>

#include <iostream>



class DataManager

{

public:

DataManager()

{

}

~DataManager()

{

if( !TestData.empty() )

TestData.clear();

}


void init()

{

for( int i = 0; i < 1000 ; i++ )

{

TestData.push_back( i );

}

}


void set( int _value )

{

TestData[ _value ] = _value * 100;

}


int get( int _value )

{

return TestData[ _value ];

}


private:

std::vector<int> TestData;


};


class TheadManager

{

public:

TheadManager()

{

memset( _thread, 0x00, sizeof( _thread) );

}

~TheadManager()

{

}


public:


void init()

{

data.init();

}


void start(int N)

{

this->init();


for( int i = 0; i< 10; i++ )

{

_thread[i] = boost::thread(&TheadManager::TestDataModify, this, N );

}

}


void join()

{

for(int i = 0; i< 10; i++ )

{

_thread[i].join();

}

}


void TestDataModify( unsigned N )

{

float ms = N;// * 1e3;

boost::posix_time::microsec timer( ms );


/*std::cout << "debug: " 

<< "ms : " << ms

<< "\nset data : " << ms

<< std::endl;*/

//data.set(ms);


for( int i = 0; i < 10 ; i++ )

{

boost::this_thread::sleep( timer );

//std::cout << "get Data : " << data.get( ms ) << " " << "thread id : " << boost::this_thread::get_id() << std::endl;

std::cout << "get Data : " << data.get( i ) << " " << "thread id : " << boost::this_thread::get_id() << std::endl;

}

}


private:

// DataManager 관리

DataManager data;


// thread

boost::thread _thread[10];


};


int main()

{

TheadManager test;

test.start( 1 );


test.join();

return 0;

}


멀티스레드가 동작이 되는지만 검사하기 위해서 급조해서 만들어 봤습니다. 이제 여기기 mutex을 넣어 좀더 

세밀하게 조율하도록하겠습니다. 

동작여부 검사하기



thread id을 보시면 멀티스레드가 동작하는 것을 볼 수 있습니다. 임의적으로 테스트 하기 위해서  간단하게 만든

것을 가지고 이렇게 하는구나 생각하시면 곤란합니다.

void TestDataModify( unsigned N )

{

float ms = N;// * 1e3;

boost::posix_time::microsec timer( ms );


/*std::cout << "debug: " 

<< "ms : " << ms

<< "\nset data : " << ms

<< std::endl;*/

//data.set(ms);


for( int i = 0; i < 10 ; i++ )

{

boost::this_thread::sleep( timer );

//std::cout << "get Data : " << data.get( ms ) << " " << "thread id : " << boost::this_thread::get_id() << std::endl;

std::cout << "get Data : " << data.get( i ) << " " << "thread id : " << boost::this_thread::get_id() << std::endl;

}

}

 

여기서 다시 수정해야 될 부분은 스래드 10개중에 5개는 read() 5개는 write()로 분류해서 만들어서 분류하여 작업

하면 다음과 같이 아래처럼 만들수 있겠죠? 어차피 간단하게 만드는 거라 넘어가주세요.

다음과 같이 변경하시면 됩니다.

#include <boost/thread/thread.hpp>

#include <boost/thread/mutex.hpp>

#include <vector>

#include <iostream>



class DataManager

{

public:

DataManager()

{

}

~DataManager()

{

if( !TestData.empty() )

TestData.clear();

}


void init()

{

for( int i = 0; i < 1000 ; i++ )

{

TestData.push_back( i );

}

}


void set( int _value )

{

TestData[ _value ] = _value * 100;

}


int get( int _value )

{

return TestData[ _value ];

}


private:

std::vector<int> TestData;


};


class TheadManager

{

public:

TheadManager() : state( true )

{

memset( _thread, 0x00, sizeof( _thread) );

}

~TheadManager()

{

}


public:


void init()

{

data.init();

}


void start(int N)

{

this->init();


for( int i = 0; i< 5; i++ )

{

_thread[i] = boost::thread(&TheadManager::Read, this, N );

}


for( int i = 5; i< 10; i++)

{

_thread[i] = boost::thread(&TheadManager::Write, this, N );

}

}


void join()

{

for(int i = 0; i< 10; i++ )

{

_thread[i].join();

}

}


void Write( unsigned N )

{

float ms = N;// * 1e3;

boost::posix_time::microsec timer( ms );

boost::this_thread::sleep( timer );

int i = 0;

while( i < 1000 )

{


boost::this_thread::sleep( timer );

boost::mutex::scoped_lock lock( _mutex );

//std::cout << "get Data : " << i << " value : " << data.get( i ) << " " << "thread id : " << boost::this_thread::get_id() << std::endl;

data.set( i );

i++;

}

}


void Read( unsigned N )

{

float ms = N;// * 1e3;

boost::posix_time::microsec timer( ms );


/*std::cout << "debug: " 

<< "ms : " << ms

<< "\nset data : " << ms

<< std::endl;*/

//data.set(ms);


//for( int i = 0; i < 10 ; i++ )

//{

// boost::this_thread::sleep( timer );

// //std::cout << "get Data : " << data.get( ms ) << " " << "thread id : " << boost::this_thread::get_id() << std::endl;

// std::cout << "get Data : " << data.get( i ) << " " << "thread id : " << boost::this_thread::get_id() << std::endl;

//}


int i = 0;

while( i < 1000 )

{


boost::this_thread::sleep( timer );

boost::mutex::scoped_lock lock( _mutex );

std::cout << "get Data : " << i << " value : " << data.get( i ) << " " << "thread id : " << boost::this_thread::get_id() << std::endl;

i++;

}

}


private:

// DataManager 관리

DataManager data;


// thread

boost::thread _thread[10];


volatile bool state;


boost::mutex _mutex;


};


int main()

{

TheadManager test;

test.start( 1 );


test.join();

return 0;

}




일단 간단하게 만들어 봤습니다. scoped_lock을 이용하여 만들어 봤습니다. 

추가적으로 thread에 대해서 포스팅 하도록 하겠습니다.

 

'프로그램언어 > boost' 카테고리의 다른 글

[ Boost ] Boost::bind #1  (0) 2011.05.12
[ Boost ] Boost::thread #4  (0) 2011.05.12
[ Boost ] Boost::thread #2  (0) 2011.05.11
[ Boost ] Boost.thread #1  (2) 2011.05.03
[ Boost ] Boost.array 관련 예제 만들어보기  (0) 2011.05.03