#include <windows.h>
#include <stdio.h>DWORD WINAPI Fun1Proc(LPVOID lpParameter);int main(int argc, char* argv[])
{
HANDLE hThread1;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
printf("main %d thread is runing\n",GetCurrentThreadId());
CloseHandle(hThread1);
return 0;
}DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
printf("thread1 %d is running\n",GetCurrentThreadId());
return 0;
}
为什么会显示的是:
main 4120 thread is running
main 4120 thread is running
thread 2184 is running为什么会有两个main  ??
我是个新手~~~

解决方案 »

  1.   


    再怎么不同步,也不会有两个main出现把???
      

  2.   

    不是执行了两次,是flush了两次
      

  3.   

    很早以前,是一个C运行库用于单线程应用程序,另一个C运行库用于多线程应用程序。之所以采用这个设计,是由于标准C运行库是在1970年左右发明的。要在很久很久之后,才会在操作系统上出现线程的概念。标准C运行库的发明者根本没有考虑到为多线程应用程序使用C运行库的问题。让我们用一个例子来了解可能遇到的问题。
    以标准C运行库的全局变量errno为例。有的函数会在出错时设置该变量。
    假定现在有这样的一个代码段:BOOL fFailure = (system("NOTEPAD.EXE README.TXT") == -1);
    if (fFailure) {
    switch (errno) {
    case E2BIG: // Argument list or environment too big
    break;
    case ENOENT: // Command interpreter cannot be found
    break;
    case ENOEXEC: // Command interpreter has bad format
    break;
    case ENOMEM: // Insufficient memory to run command
    break;
    }
    }假设在调用了system函数之后,并在执行if语句之前,执行上述代码的线程被中断了。另外还假设,这个线程被中断后,同一个进程中的另一个线程开始执行,而且这个新线程将执行另一个C运行库函数,后者设置了全局变量errno。当CPU后来被分配回第一个线程时,对于上述代码中的system函数调用,errno反映的就不再是正确的错误码。为了解决这个问题,每个线程都需要它自己的errno变量。此外,必须有某种机制能够让一个线程引用它自己的errno变量,同时不能让它去碰另一个线程的errno变量。
    这仅仅是证明了“标准C/C++运行库最初不是为多线程应用程序而设计”的众多例子中的一个。
    在多线程环境中会出问题的C/C++运行库变量和函数有errno,_doserrno,strtok,_wcstok,strerror,_strerror,tmpnam,tmpfile,asctime,_wasctime,gmtime,_ecvt和_fcvt等等。
    为了保证C和C++多线程应用程序正常运行,必须创建一个数据结构,并使之与使用了C/C++运行库函数的每个线程关联。然后,在调用C/C++运行库函数时,那些函数必须知道去查找主调线程的数据块,从而避免影响到其他线程。
    那么,系统在创建新的线程时,是如何知道要分配这个数据块的呢?答案是它并不知道。系统并不知道应用程序是用C/C++来写的,不知道你调用的函数并非天生就是线程安全的。保证线程安全是程序员的责任。创建新线程时,一定不要调用操作系统的CreateThread函数。相反,必须调用C/C++运行库函数_beginthreadex。
    对于_beginthreadex函数,每个线程都有自己的专用_tiddata内存块,它们是从C/C++运行库的堆(heap)上分配的。用_beginthreadex而不要用CreateThread创建线程。而_beginthreadex是用于多线程应用程序的C运行库中函数,要想编译通过,必须在 Project->Setting->c/C++->Code Generation->Use Run Library中选择多线程选项(Multithreaded 或者 Debug Multithreaded)。之后你会发现,使用了多线程运行库之后,即使使用CreateThread函数也不会出错了。
      

  4.   

    嗯,C/C++库和多线程不兼容,请用_beginthreadex()。如果是MFC程序,请用AfxBeginThread()
      

  5.   

    额~~~肯定不会每次都输出两次啊,我也知道应该使用_beginthreadex,我只是想知道为什么CreateThread会出现两个main而已(有时候是出项两次thread)........
      

  6.   

    简单,用ollydbg入初始状态设条件断点。在你的code中加条件变量,然后设断运行。断下来之后分析即可。
      

  7.   

    我刚刚在Win7下用VS2010编译后运行了N次,一般都是:
    main 4120 thread is running
    大概1/10几率会:
    main 4120 thread is running
    thread 2184 is running没有出现LZ所说的情况
      

  8.   

    _beginthreadex也是用CreateThread实现的,只是为每个线程创建了一个运行环境而已,使得在多线程环境下可以调用strtok等用到全局变量的函数
      

  9.   

    printf会把文字放到缓冲区中然后flush,这两个线程同时干这事就可能第一个线程没flush完第二个线程就flush,导致输出两次
      

  10.   

    fprintf(stderr,"main %d thread is runing\n",GetCurrentThreadId());
    fprintf(stderr,"thread1 %d is running\n",GetCurrentThreadId());好吧,我把代码改这这样,stderr应该不经过缓冲区吧~~~但是结果还是出现了两个main(有时候 出现)...好纠结啊~~~~~~~~~~~~~~
      

  11.   

    你怎么确定stderr应该不经过缓冲区,它是有个临时缓冲区然后立即flush,所以还是会出问题
    要想真没运行库的缓冲,用这个DWORD WINAPI Fun1Proc(LPVOID lpParameter);
    int main(int argc, char* argv[])
    {
        HANDLE hThread1;
        hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);    
    char ccc[256];DWORD count=
    sprintf(ccc,"main %d thread is runing\n",GetCurrentThreadId());
        WriteFile(GetStdHandle(-11),ccc,count,&count,0);
        CloseHandle(hThread1);    
        return 0;
    }DWORD WINAPI Fun1Proc(LPVOID lpParameter)
    {
    char ccc[256];DWORD count=
        sprintf(ccc,"thread1 %d is running\n",GetCurrentThreadId());
    WriteFile(GetStdHandle(-11),ccc,count,&count,0);
        return 0;
    }