none
为什么 主线程中的printf函数会被多次重复使用呢 ? RRS feed

  • 问题

  • #include <windows.h>
    #include <stdio.h>
    #include "u_task.h"
    
    HANDLE test_entry_func(char *name)
    {
      printf("%s\n", name);
      Sleep(1000);
      while(TRUE) {
        printf("%s, %d\n", __FILE__, __LINE__);
        Sleep(500);
      }
    }
    
    
    
    
    int main(int argc, char **argv)
    {
      UINT32 ret;
      ret = TASK_CreateThread(NULL, NULL, test_entry_func, "zhong");
      ret += 100;
      printf("sakdja %d\n", ret);
      Sleep(2000);
    
      return 0;
    }

    我使用上述代码测试多线程程序时,发现程序偶然显示(重复2次打印sakdja 100)

    sakdja 100
    sakdja 100
    zhong
    D:\Program_Files\Microsoft Visual Studio\MyProjects\tt\bcd.cpp, 11
    D:\Program_Files\Microsoft Visual Studio\MyProjects\tt\bcd.cpp, 11
    D:\Program_Files\Microsoft Visual Studio\MyProjects\tt\bcd.cpp, 11
    Press any key to continue

    偶然又显示                        (仅1次打印sakdja 100)

    sakdja 100
    zhong
    D:\Program_Files\Microsoft Visual Studio\MyProjects\tt\bcd.cpp, 11
    D:\Program_Files\Microsoft Visual Studio\MyProjects\tt\bcd.cpp, 11
    D:\Program_Files\Microsoft Visual Studio\MyProjects\tt\bcd.cpp, 11
    Press any key to continue

    这是为什么呢 ?


    清钟沁桐
    2010年7月2日 16:43

答案

全部回复

  • 你这个是VC6吧?

    是标准输出缓存没有正确处理的缘故。要知道标准输出是共享资源,你使用他时必须进行并发控制。 

    假定第一个线程输出sakdja 100....后,cout尝试把其缓存清空,但是在清空前的一霎那,如果恰好线程2获得控制权,你说的现象就必然出现。

    2010年7月3日 13:18
  • "Tr0j4n" wrote:
    > 你这个是VC6吧?
    > 是标准输出缓存没有正确处理的缘故。要知道标准输出是共享资源,你使用他时必须进行并发控制。
    > 假定第一个线程输出sakdja 100....后,cout尝试把其缓存清空,但是在清空前的一霎那,如果恰好线程2获得控制权,你说的现象就必然出现。
     
    至少VC4已有对printf的并发控制, printf先_lock_file2(win32是EnterCriticalSection), 然后把stream->_ptr回置为stream->_base.
     
    所以VC6的printf不需要自己额外并发控制, 而且"缓存清空"(即缓存指针回置)是printf在打印之前做的, 并非printf在打印之后做的.
     
     
    我就是使用VC6才出现这个错误的

    清钟沁桐
    2010年7月4日 13:10
  •  
     
    • 已标记为答案 vfdff 2010年7月5日 14:57
    2010年7月5日 3:35