// event1.cpp : Defines the entry point for the console application.
//// test cases:
// send threads: 2,  per thread: 10
// send threads: 20, per thread: 100
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <iomanip>
#include <list>using namespace std;//MyPool g_pool;///////////////////////////////////////////////////////////////////////////////
class MyMutex {
public:
MyMutex();
~MyMutex();
int Lock();
int UnLock();
private:
HANDLE m_object;
};MyMutex::MyMutex() {
cout << "MyMutex::MyMutex" << endl;
m_object = ::CreateMutex(NULL, FALSE, NULL);
}
MyMutex::~MyMutex() {
cout << "MyMutex::~MyMutex" << endl;
::CloseHandle(m_object);
}
int MyMutex::Lock() {
return (::WaitForSingleObject(m_object, INFINITE) == WAIT_FAILED) ? -1 : 0;
}
int MyMutex::UnLock() {
return (::ReleaseMutex(m_object) == 0) ? -1 : 0;
}
///////////////////////////////////////////////////////////////////////////////
class MyClass {
public:
MyClass(int id);
~MyClass();
int GetID();
private:
int m_id;
};MyClass::MyClass(int id) {
m_id = id;
}
MyClass::~MyClass() {
}
int MyClass::GetID() {
return m_id;
}
///////////////////////////////////////////////////////////////////////////////
extern MyMutex g_FileLock;
class MyPool {
public:
MyPool();
~MyPool();
MyClass* Get();
void     Put(MyClass* p);
private:
list<MyClass*> m_list;
HANDLE         m_event;
MyMutex        m_lock;
};MyPool::MyPool() {
cout << "MyPool::MyPool" << endl;
//m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
m_event = ::CreateEvent(NULL, FALSE, FALSE, NULL);
}
MyPool::~MyPool() {
cout << "MyPool::~MyPool" << endl;
::CloseHandle(m_event);
}
MyClass* MyPool::Get() {
MyClass* ret;
DWORD dwRet = -1;
DWORD tid = GetCurrentThreadId();re:
m_lock.Lock();
while (m_list.size()==0) {
g_FileLock.Lock();
cout << "Thread(" << setw(4) <<tid<<") " << "no node now, waitting... ..." << endl;
g_FileLock.UnLock();
// simulation of pthread_cond_wait
m_lock.UnLock();
//::Sleep(1000);
dwRet = ::WaitForSingleObject(m_event, INFINITE);
if (dwRet==WAIT_OBJECT_0) {
g_FileLock.Lock();
cout <<"Thread(" <<tid<<") " "success return from wait function" << endl;
g_FileLock.UnLock();
goto re;
}
}
ret = *(m_list.begin());
m_list.pop_front(); /*
if (m_list.size()==0) {
m_lock.UnLock();
return NULL;
}
ret = *(m_list.begin());
m_list.pop_front();*/ m_lock.UnLock(); return ret;
}
void MyPool::Put(MyClass* p) {
m_lock.Lock(); m_list.push_back(p);
::SetEvent(m_event); /*m_list.push_back(p);*/ m_lock.UnLock();
}
///////////////////////////////////////////////////////////////////////////////
MyPool  g_pool;MyMutex g_FileLock;DWORD WINAPI put_thread(LPVOID arg);
DWORD WINAPI get_thread(LPVOID arg);DWORD WINAPI put_thread(LPVOID arg) {
int *p = (int*)arg;
DWORD tid = ::GetCurrentThreadId(); int base = *p * 100;
//for (int i=0; i<10; ++i) {
for (int i=base; i<base+100; ++i) {
MyClass* tmp = new MyClass(i);
g_pool.Put(tmp);
g_FileLock.Lock();
cout << "Thread(" <<tid<<") "<<"put::" << i << endl;
g_FileLock.UnLock();
} delete p;
return 0;
}DWORD WINAPI get_thread(LPVOID arg) {
DWORD tid = ::GetCurrentThreadId();
while (1) {
MyClass* tmp = g_pool.Get();
if (tmp == NULL) {
g_FileLock.Lock();
cout <<"Thread(" <<tid<<") "<< "no data find" << endl;
g_FileLock.UnLock();
::Sleep(1000);
continue;
}
int i = tmp->GetID();
g_FileLock.Lock();
cout << "Thread(" <<tid<<") "<<"get::" << i << endl;
g_FileLock.UnLock();
delete tmp;
}
}//MyPool g_pool;int main(int argc, char* argv[])
{
//MyMutex MyLock;
HANDLE get_thd[20];
HANDLE put_thd[10];
DWORD  dwThreadId; int* tag=NULL; // put threads, about 64 max threads count
// for (int i=0; i<2000; ++i) {  // cant create too much threads //for (int i=0; i<2; ++i) {
//for (int i=0; i<20; ++i) {
for (int i=0; i<1; ++i) {
tag = new int(i);
put_thd[i] = CreateThread(
NULL,                        // default security attributes
0,                           // use default stack size
put_thread,                  // thread function
(LPVOID)tag,                 // argument to thread function
0,                           // use default creation flags
&dwThreadId);                // returns the thread identifier
if (put_thd[i] == NULL) {
g_FileLock.Lock();
fprintf(stderr, "Thread(main) create put thread(%d) error\n", i);
g_FileLock.UnLock();
} else {
g_FileLock.Lock();
fprintf(stderr, "Thread(main) create put thread(%d) success\n", i);
g_FileLock.UnLock();
}
} // get threads
//for (i=0; i<5; ++i) {
for (i=0; i<3; ++i) {
get_thd[i] = CreateThread(
NULL,                        // default security attributes
0,                           // use default stack size
get_thread,                  // thread function
NULL,                        // argument to thread function
0,                           // use default creation flags
&dwThreadId);                // returns the thread identifier
if (get_thd[i] == NULL) {
g_FileLock.Lock();
fprintf(stderr, "Thread(main) create get thread(%d) error\n", i);
g_FileLock.UnLock();
} else {
g_FileLock.Lock();
fprintf(stderr, "Thread(main) create get thread(%d) success\n", i);
g_FileLock.UnLock();
}
} while (1) ::Sleep(1000); return 0;
}
///////////////////////////////////////////////////////////////////////////////

解决方案 »

  1.   

    诸位windows开发高手帮帮忙吧,兄弟我搞不定了
      

  2.   

    原来是vc的连接多线程库的问题: 默认情况下vc连接的是"Single-thread debug dll", 这种情况下
    的new / delete不是线程安全的, 修改工程选项使之连接"Multi-thread debug dll" 就没有问题了
    ... ...此问题至少在10天之内毫无解决思路, 2周以后才逐步想到这方面, 可见软件开发的复杂性不是人们可以
    想象的, 以此做个记录... ...
      

  3.   

    哎,没有记住的教训!
    害苦了我,两天尽在想怎么崩溃在stl里面呢?谢谢楼主分享:)andylin