pthread 와 c++
글쓴이: musik / 작성시간: 수, 2003/04/09 - 12:21오후
간단한 큐를 만들어 테스트하던 중입니다.
이상하게 inserter 쓰레드에서 큐의 put 을 호출할때 세그폴트가 나면서 죽는 경우가 있습니다.
도무지 원인을 모르겠습니다. STL 과 thread 간의 문제인가요?....
또한, 로컬스코프내에 선언된 변수, 즉 스택에 위치하는 변수를 따로
동기화를 해주어햐 할 필요가 있는 경우도 있나요?
스택을 공유하는 경우도 있다고 들은것 같은데... 고수님들의 조언을 부탁
드립니다.
감사합니다.
------------------------------------------------------------
#include <iostream> #include <strstream> #include <string> #include <deque> #include <pthread.h> #include <thread.h> #include <unistd.h> using namespace std; pthread_mutex_t qmutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t qcond = PTHREAD_COND_INITIALIZER; class QItem { public: QItem(string s):data_(s) {} string data_; }; class Queue { public: Queue() {} void put(QItem item); QItem get(); private: deque<QItem> elems_; }; void Queue::put(QItem item) { pthread_mutex_lock(&qmutex); elems_.push_back(item); pthread_cond_signal(&qcond); pthread_mutex_unlock(&qmutex); } QItem Queue::get() { pthread_mutex_lock(&qmutex); while (elems_.empty()) { pthread_cond_wait(&qcond, &qmutex); } QItem ret = *(elems_.begin()); elems_.pop_front(); pthread_mutex_unlock(&qmutex); return ret; } ////////////// Queue queue; void* inserter(void* arg) { int i=0; while (true) { ostrstream os; os << i++; queue.put(QItem(os.str())); // 여기서 죽는것으로 보임 } } int main() { pthread_t thread; void *ttt; thr_setconcurrency(2); pthread_create(&thread, 0, inserter, 0); while (true) { QItem item = queue.get(); cout << item.data_ << endl; } }
Forums:
문제의 원인
쓰레드가 스케쥴링 될때,
멀티프로세스 환경이 아니라면,
님께서 의도한데로 두개의 동작이 동시에 일어나지 않습니다.
삽입하는 쓰레드와 퍼내는 메인 프로그램이 번갈아 가면서
실행하는데, 삽입하는 녀석에 비해서 꺼내는 녀석이 더 일을 적게해서
결국엔 데크에 삽입하다가 메모리 부족으로 죽어 버리게 되는 거죠..
(os가 동일한 퀀텀을 할당해도 꺼내는 녀석이
cout으로 출력하는 것 때문에 부하가 더 큰듯합니다.
정확한거는 profiler를 돌려보면 명확할듯 싶네요)
삽입하는 녀석에게 약간의 슬립을 준다면
죽을일이 없을것 같네요..
울랄라~ 호기심 천국~!!
http://www.ezdoum.com
음.. 한계치에 대한 설정이 필요하지 않을까요? 그런 한계값 없이 계
음.. 한계치에 대한 설정이 필요하지 않을까요?
그런 한계값 없이 계속 넣는다는건 좀 위험해 보일거 같아요.
위분 말대로 몇개 넣고 죽는지 확인해보세요.
일정하게 수에서 죽는다면 윗분 말이 맞을듯..
screen + vim + ctags 좋아요~
[code:1]void*inserter(void* arg&
------------------------------------------------------------------------
위와 같이 수정하고 돌려보았습니다.
죽는 시점은 데크에 데이터가 얼마나 들어가든 상관없이... 즉, 불규칙하게
죽습니다. 코어파일을 살펴보면 실제로 메모리가 넘치는 것과는 상관이
없어보이는, STL 관련 부분에서 죽은 것으로 보입니다. (string asign 부분)
( g++ version 2.95.2, Solaris7 )
그리고, 실제로 멀티 CPU 환경이기때문에 쓰레드가 동시에 돌고 있을것으로
보입니다.
STL 에서 쓰레드 안전성을 보장을 못한다고 해도, 이 코드에서 쓰인부분은
local 스코프에서 선언되어 쓰인것인데... 왜 이런지 모르겠습니다.
이건 별도의 질문인데.. 다른 쓰레드가 서로의 스택에 침입할수 있나요?
즉 같은 코드영역을 실행한다해도 서로의 로컬변수를 침입할수도 있나요?
좀 어리석은 질문같지만.. 하도 이상해서 질문드립니다.
지도편달 바랍니다.
답변이 아닌듯 싶기도 하네요.
세그멘트폴트라면 메모리의 할당부분인데
잘은 모르겠습니다.
혹시나 하는 맘에.
void put(QItem item);
QItem get();
을
void put (QItem& item);
QItem & get() 을 행해주심이 좋을듯 하군요.
deque<queue<datatype> > 을 사용하시는것도 좋을듯싶습니다.
#include <queue> 아시는데 괜시리. 하는듯. 하네요.
집에가서 해보고 사족 더달지용.
어
전 왜 코드가 실행이 안되죠?gcc 2.95.3, solaris
전 왜 코드가 실행이 안되죠?
gcc 2.95.3, solaris 9
화면상에 출력되는게 없네요..
screen + vim + ctags 좋아요~
string대신에
vector<char>을 사용해보시는건 어떨지요.
string이 COW기법으로 구현되어있다면 MT환경에서 사용하는 것은 위험할 수 있다고 알고 있습니다. string의 사용자 입장에서는 string끼리 공유하고 있는 데이터에 대해서는 동기화를 수행할 방법이 없기 때문이지요.
문제는 ostrstream 인듯...
솔라리스에서는 왠일인지 화면에 아무것도 표시가 안되서 리눅스에서
이리저리 테스트해본 결과입니다만...
insert()함수 정의에서
ostrstream 을 빼고
버퍼하나만들고
snprintf 를 사용하니
500만개까지는 아무런 문제가 없었습니다. (이젠 머 버퍼크기가 문제겠지만 설마 번호가...)
g++2.95에서 스트림 라이브러리 구현이 완전하지 않다는 문서를 본적이 있는데, 한번 확인해 보시지요...
답변 적을 수 있는 날이 오다니 ㅋㅋ
저두 솔라리스에서 2.95.3을 가지고 thread프로그램하다가
고생 많이했읍니다. 2.95.3에서는 SGI STL을 사용하는 쓰레드 세이프하다고 문서는 되어있는데 STL을 사용하다가 메모리를 재 할당하는 부분에서 문제가 계속 발생하더라구요
이문제는 GCC 3.2.x버젼에는 문제 없이 동작합니다.
3.2.x부터는 GNU STL을 사용하는것 같읍니다. 같은 소스코드를
컴파일러에 따라서 한번 수행해 보시구요
노파심에 컴파일 하실 경우 두가지 플래그 설정하는것 있지 마시구요.
-D_REENTRANT -D_PTHREADS
그럼 도움이 되었으면 합니다.
Perl 만세~~~
2.95에서도 안전하게...
gcc 3.X 가 좀 아직 찜찜하시면,
stlport 를 쓰시면 됩니다.
http://www.stlport.org/
문제는 컴파일/링킹 ?
위의 분이 말씀하신 사항에 한표를.. ^_^;;
컴파일시 -D_PTHREADS 하셨는가 확인해보셨나요.
g++ 2.95.x 를 쓰신다고 하셨는데... stl_config.h 파일 항목을 보시면
다음과 같은게 있어요
// * _PTHREADS: if defined, use Posix threads for multithreading support.
그리고.. 솔라리스에서 아무 것도 출력이 안된다는 의견도 있었는데..
이 경우는 아무래도 링크시에 -lpthread 를 해주지 않으셨나 의심이 듭니다..
두개 다 제가 많이 하던 실수죠 ^___^
댓글 달기