青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Kisser Leon

這個kisser不太冷
posts - 100, comments - 102, trackbacks - 0, articles - 0

多線程學習中碰到的一個很有意思的問題

Posted on 2007-03-27 21:24 kk 閱讀(5186) 評論(11)  編輯 收藏 引用 所屬分類: IT

#include <stdio.h>
#include <windows.h>

const int numThreads = 3;

?

DWORD WINAPI helloFunc(LPVOID pArg)

{

?????? int num = (int) pArg;

?????? printf("Hello Thread %d\n", num);

??????

?????? return 0;

}

?

int main()

{?????

?????? HANDLE hThread[numThreads];

?

?????? for (int i = 0; i < numThreads; i++)

?????? {

????????????? hThread[i] = CreateThread(NULL, 0, helloFunc, (LPVOID)i, 0, NULL);

?????? }

?

?????? WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE);

?

?????? return 0;

}

?

上面可以說是一個最簡單的多線程程序了。

運行時庫選項:

(1) ????? 單線程調試 (/MLd)

(2) ????? 多線程調試 DLL (/MDd)

(3) ????? 多線程調試 (/MTd)

上面三個是 debug 版本的,還有與它們相對的三個 release 版本等。

由于一開始的時候系統默認的是 /MLd ,所以產生一些很有意思的問題,比如說有些線程 的線程函數會被執行多次:

Hello Thread 1

Hello Thread 1

Hello Thread 0

Hello Thread 2

Press any key to continue

線程 1 被執行了兩次!

Hello Thread 0

Hello Thread Hello Thread 1

Hello Thread Hello Thread 1

2

Press any key to continue

這個就更奇怪了!雖然是因為有 race condition 在,但是為什么會多出一個 Hello Thread 呢( 5 Hello Thread 4 個數字)?那就只有一個原因,有一個數字被覆蓋了(難道會有可能沒來得及輸出嗎?)!

Intel Thread Checker 進行 check 的時候,會發生下面這樣的問題,甚是奇怪!

圖片傳不上來。下次再傳。終于上傳成功了,娃哈哈
P1.bmp


碰到這么多問題,因為偶是初學者,所以就一直沒有察覺出來編譯選項設置有問題。而且我一直覺得都是對的。只是對其中的一個線程的線程函數為什么會執行兩遍感覺很
confuse WHY WHY WHY Google 一個線程的線程函數是否可以執行兩遍,找不到有用的咚咚! Baidu 也沒有相關信息。哭。只能暫時放棄,不過我始終還是不明白一個線程的線程函數為什么可以執行多次?我也沒有見過這樣的例子。可能這個問題在俺腦子里走太多路了,今天突發奇想,會不會是編譯選項有問題?檢查了一下才發現原來一開始忘了把它設為多線程的了,設回來之后就一切正常了,試了 N 多次都沒有碰到過問題(雖然這不能證明肯定沒有問題!線程執行順序是不可預料的!要看 CPU 的心情的, J )。

?

Next, 接下來查一下編譯器相關資料。

Multithreaded Libraries Performance?

The single-threaded CRT is no longer in vs2005 available. This topic discusses how to get the maximum performance from the multithreaded libraries.

The performance of the multithreaded libraries has been improved and is close to the performance of the now-eliminated single-threaded libraries. For those situations when even higher performance is required, there are several new features.

·???????? Independent stream locking allows you to lock a stream and then use _nolock Functions that access the stream directly. This allows lock usage to be hoisted outside critical loops.

·???????? Per-thread locale reduces the cost of locale access for multithreaded scenarios (see _configthreadlocale).

·???????? Locale-dependent functions (with names ending in _l) take the locale as a parameter, removing substantial cost (for example, printf, _printf_l, wprintf, _wprintf_l).

·???????? Optimizations for common codepages reduce the cost of many short operations.

·???????? Defining _CRT_DISABLE_PERFCRIT_LOCKS forces all I/O operations to assume a single-threaded I/O model and use the _nolock forms of the functions. This allows highly I/O-based single-threaded applications to get better performance.

·???????? Exposure of the CRT heap handle allows you to enable the Windows Low Fragmentation Heap (LFH) for the CRT heap, which can substantially improve performance in highly scaled scenarios.

?

運行時庫是程序在運行時所需要的庫文件 ,通常運行時庫是以 LIB DLL 形式提供的。 C 運行時庫誕生于 20 世紀 70 年代,當時的程序世界還很單純,應用程序都是單線程的,多任務或多線程機制在此時還屬于新觀念。所以這個時期的 C 運行時庫都是單線程的。

隨著操作系統多線程技術的發展,最初的 C 運行時庫無法滿足程序的需求,出現了嚴重的問題。 C 運行時庫使用了多個全局變量(例如 errno )和靜態變量,這可能在多線程程序中引起沖突。假設兩個線程都同時設置 errno ,其結果是后設置的 errno 會將先前的覆蓋,用戶得不到正確的錯誤信息。

  因此, Visual C++ 提供了兩種版本的 C 運行時庫。一個版本供單線程應用程序調用,另一個版本供多線程應用程序調用。多線程運行時庫與單線程運行時庫有兩個重大差別:
  ( 1 )類似 errno 的全局變量,每個線程單獨設置一個。這樣從每個線程中可以獲取正確的錯誤信息。
  ( 2 )多線程庫中的數據結構以同步機制加以保護。這樣可以避免訪問時候的沖突。

   Visual C++ 提供的多線程運行時庫又分為靜態鏈接庫和動態鏈接庫兩類,而每一類運行時庫又可再分為 debug 版和 release 版,因此 Visual C++ 共提供了 6 個運行時庫。如下表:

C 運行時庫

庫文件

Single thread(static link) ML

libc.lib

Debug single thread(static link) MLd

libcd.lib

MultiThread(static link) ?MT

libcmt.lib

Debug multiThread(static link) MTd

libcmtd.lib

MultiThread(dynamic link) MD

msvert.lib

Debug multiThread(dynamic link) MDd

msvertd.lib


   2.C 運行時庫的作用
   C 運行時庫除了給我們提供必要的庫函數調用(如 memcpy printf malloc 等)之外,它提供的另一個最重要的功能是為應用程序添加啟動函數。
   C 運行時庫啟動函數的主要功能為進行程序的初始化,對全局變量進行賦初值,加載用戶程序的入口函數。
  不采用寬字符集的控制臺程序的入口點為 mainCRTStartup(void) 。下面我們以該函數為例來分析運行時庫究竟為我們添加了怎樣的入口程序。這個函數在 crt0.c 中被定義,下列的代碼經過了筆者的整理和簡化:

void mainCRTStartup(void)
{
  int mainret;
  /* 獲得 WIN32 完整的版本信息 */
  _osver = GetVersion();
  _winminor = (_osver >> 8) & 0x00FF ;
  _winmajor = _osver & 0x00FF ;
  _winver = (_winmajor << 8) + _winminor;
  _osver = (_osver >> 16) & 0x00FFFF ;

  _ioinit(); /* initialize lowio */

  /* 獲得命令行信息 */
  _acmdln = (char *) GetCommandLineA();

  /* 獲得環境信息 */
  _aenvptr = (char *) __crtGetEnvironmentStringsA();

  _setargv(); /* 設置命令行參數 */
  _setenvp(); /* 設置環境參數 */

  _cinit(); /* C 數據初始化:全局變量初始化,就在這里! */

  __initenv = _environ;
  mainret = main( __argc, __argv, _environ ); /* 調用 main 函數 */

  exit( mainret );
}

從以上代碼可知,運行庫在調用用戶程序的 main WinMain 函數之前,進行了一些初始化工作。初始化完成后,接著才調用了我們編寫的 main WinMain 函數。只有這樣,我們的 C 語言運行時庫和應用程序才能正常地工作起來。

  除了 crt0.c 外, C 運行時庫中還包含 wcrt0.c wincrt0.c wwincrt0.c 三個文件用來提供初始化函數。 wcrt0.c crt0.c 的寬字符集版, wincrt0.c 中包含 windows 應用程序的入口函數,而 wwincrt0.c 則是 wincrt0.c 的寬字符集版。

   Visual C++ 的運行時庫源代碼缺省情況下不被安裝。如果您想查看其源代碼,則需要重裝 Visual C++ ,并在重裝在時選中安裝運行庫源代碼選項。

3.
各種 C 運行時庫的區別

  ( 1 )靜態鏈接的單線程庫
  靜態鏈接的單線程庫只能用于單線程的應用程序 C 運行時庫的目標代碼最終被編譯在應用程序的二進制文件中。通過 /ML 編譯選項可以設置 Visual C++ 使用靜態鏈接的單線程庫。

  ( 2 )靜態鏈接的多線程庫
  靜態鏈接的多線程庫的目標代碼也最終被編譯在應用程序的二進制文件中,但是它可以在多線程程序中使用。通過 /MT 編譯選項可以設置 Visual C++ 使用靜態鏈接的單線程庫。

  ( 3 )動態鏈接的運行時庫
  動態鏈接的運行時庫將所有的 C 庫函數保存在一個單獨的動態鏈接庫 MSVCRTxx.DLL 中, MSVCRTxx.DLL 處理了多線程問題。使用 /MD 編譯選項可以設置 Visual C++ 使用動態鏈接的運行時庫。

   /MDd /MLd /MTd 選項使用 Debug runtime library( 調試版本的運行時刻函數庫 ) ,與 /MD /ML /MT 分別對應。 Debug 版本的 Runtime Library 包含了調試信息,并采用了一些保護機制以幫助發現錯誤,加強了對錯誤的檢測,因此在運行性能方面比不上 Release 版本。

  下面看一個未正確使用 C 運行時庫的控制臺程序

#include <stdio.h>
#include <afx.h>
int main()
{
  CFile file;
  CString str("I love you");
  TRY
  {
   file.Open("file.dat",CFile::modeWrite | CFile::modeCreate);
  }
  CATCH( CFileException, e )
  {
   #ifdef _DEBUG
   afxDump << "File could not be opened " << e->m_cause << "\n";
   #endif
  }
  END_CATCH

  file.Write(str,str.GetLength());
  file.Close();
}

我們在 "rebuild all" 的時候發生了 link 錯誤:

nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
main.exe : fatal error LNK1120: 2 unresolved externals
Error executing cl.exe.

發生錯誤的原因在于 Visual C++ 對控制臺程序默認使用單線程的靜態鏈接庫,而 MFC 中的 CFile 類已暗藏了多線程。我們只需要在 Visual C++6.0 中依次點選 Project->Settings->C/C++ 菜單和選項,在 Project Options 里修改編譯選項即可。

不過最上面的那個程序在 6.0里面是可以運行的,現象同2003的是一樣的。
***********************************************

?

從字面上看,運行庫是程序在運行時所需要的庫文件。通常運行庫是以 DLL 形式提供的。 Delphi C++ Builder 的運行庫為 .bpl 文件,實際還是一個 DLL 。運行庫中一般包括編程時常用的函數,如字符串操作、文件操作、界面等內容。不同的語言所支持的函數通常是不同的,所以使用的庫也是完全不同的,這就是為什么有 VB 運行庫、 C 運行庫、 Delphi 運行庫之分的原因。即使都是 C++ 語言,也可能因為提供的函數不同,而使用不同的庫。如 VC++ 使用的運行庫和 C++ Builder 就完全不同。

如果不使用運行庫,每個程序中都會包括很多重復的代碼,而使用運行庫,可以大大縮小編譯后的程序的大小。但另一方面,由于使用了運行庫,所以在分發程序時就必須帶有這些庫,比較麻煩。如果在操作系統中找不到相應的運行庫程序就無法運行。為了解決這個矛盾, Windows 總是會帶上它自己開發的軟件的最新的運行庫。象 Windows 2000 以后的版本都包括 Visual Basic 5.0/6.0 的庫。 Internet Explorer 總是帶有最新的 Visual C++ 6.0 的庫。 Windows XP 帶有 Microsoft .NET 1.0 (用于 VB.NET C# )的庫。 Visual C++ Delphi C++ Builder 允許用戶選擇所編譯得到的程序是否依賴于運行庫。而 VB FoxPro PowerBuilder LabWindows/CVI Matlab 就不允許用戶進行這種選擇,必須依賴于運行庫。

?

小結

看了上面這么多咚咚以后(我估計沒幾個人會有這個耐心把這么多東西看完的,娃哈哈),不過我還是把它完整地看完了,中間那一段是抄的,講得很好,講得非常清楚。嗯。有一點是可以肯定的,那就是不要用 ML 單線程版本,況且 2005 已經不支持 ML (注意,這里 ML 不是 Make L*ve 的縮寫,汗!)了。另外, ML 不支持多線程的,所以如果使用 ML 來編譯運行的話,肯定會出很多問題的,雖然它沒有明確說出會發生什么樣的問題。

一個困擾偶很長時間的問題終于解決。把 MLd 改為 MDd 所有問題就都解決了,用 Intel Thread Checker check 了一下也沒問題。如果大家有碰到同樣的問題的話,希望以上能夠給你一點有用的信息。有啥問題,歡迎與我聯系。有啥說的不對的,請批評指正。恩。

Have fun.

Feedback

# re: 多線程學習中碰到的一個很有意思的問題   回復  更多評論   

2007-03-27 21:36 by 小熊
晚上傳了n多次圖片,都沒有成功,哭
CSDN一次就pass了。sigh

# re: 多線程學習中碰到的一個很有意思的問題   回復  更多評論   

2007-03-28 12:52 by 小熊
線程函數結束,線程就結束

# re: 多線程學習中碰到的一個很有意思的問題 [未登錄]  回復  更多評論   

2007-03-30 09:27 by hdqqq
hThread[i] = CreateThread(NULL, 0, helloFunc, (LPVOID)i, 0, NULL);
上面這句是有問題的,因為CreateThread返回時候,并不保證線程已經啟動了,所以進入下一個循環后i就被修改,導致線程取得了錯誤的參數.

# re: 多線程學習中碰到的一個很有意思的問題   回復  更多評論   

2007-03-30 09:34 by 小熊
但是一個線程函數不可能被執行多次的。呵呵

# re: 多線程學習中碰到的一個很有意思的問題   回復  更多評論   

2007-03-30 13:31 by think
這樣寫倒是吃驚:(LPVOID)i
你的程序在我機子上沒有問題,也從來不遇到過

# re: 多線程學習中碰到的一個很有意思的問題   回復  更多評論   

2007-03-30 17:16 by 小熊
(LPVOID)i是沒問題的
你可以把i理解為是一個指針之類的。。。

在你的機子上沒問題的原因很可能是,你的運行時庫設置為MD或者MT了,那肯定沒問題。如果你設置為ML的話,肯定會有問題的,呵呵,或者說多運行幾次。

# re: 多線程學習中碰到的一個很有意思的問題 [未登錄]  回復  更多評論   

2007-04-05 09:16 by christanxw
本質原因是你在線程中使用了printf()這樣的非多線程安全的函數。你用它的多線程版本(/MTd或/MDd)就沒問題了,或者你在使用/MLd時對printf加鎖也不會出問題。

# re: 多線程學習中碰到的一個很有意思的問題   回復  更多評論   

2007-04-05 21:44 by 小熊
恩。不過printf()也不可能讓一個線程函數執行多次的吧?
使用了多線程版本后,printf()確實是不會有問題了。恩

# re: 多線程學習中碰到的一個很有意思的問題   回復  更多評論   

2008-10-09 17:11 by 5871
很不明白,.....

# re: 多線程學習中碰到的一個很有意思的問題   回復  更多評論   

2009-01-20 17:49 by sak
你這個人很有意思,哇哈哈
咚咚嗆cei cei 嗆

# re: 多線程學習中碰到的一個很有意思的問題 [未登錄]  回復  更多評論   

2010-04-13 20:07 by Leon
這兩天我也在做操作系統里多線程的實驗,這方面的程序確實錯得讓人匪夷所思,我那還有一個關于多線程的實驗,還有相關的錯誤總結,你如果想看的話愿意和你分享!
QQ:250575616
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久久久伊人| 亚洲人精品午夜| 国产一区二区电影在线观看 | 欧美一区二区三区四区在线观看地址 | 久久视频这里只有精品| 亚洲少妇最新在线视频| 亚洲最黄网站| 亚洲美洲欧洲综合国产一区| 亚洲欧洲另类| 在线视频亚洲| 欧美一区=区| 巨胸喷奶水www久久久免费动漫| 亚洲欧美日本伦理| 亚洲免费影院| 久久久久久色| 欧美激情一区二区三区蜜桃视频| 欧美日韩精品三区| 欧美三区在线视频| 国产精品麻豆成人av电影艾秋| 国产精品久久看| 国产亚洲综合在线| 亚洲精品乱码久久久久久蜜桃麻豆 | av成人老司机| 一区二区三区精密机械公司| 中国成人亚色综合网站| 亚洲欧美一区在线| 欧美一区二区三区四区在线观看地址 | 亚洲午夜视频| 亚洲视屏一区| 欧美+日本+国产+在线a∨观看| 开元免费观看欧美电视剧网站| 久久青草久久| 日韩一二三在线视频播| 欧美中在线观看| 欧美精品18+| 国产日韩欧美在线一区| 亚洲人午夜精品免费| 午夜宅男欧美| 91久久夜色精品国产网站| 亚洲一区二区av电影| 免费观看一区| 国产亚洲免费的视频看| 99香蕉国产精品偷在线观看| 久久精品视频免费| 亚洲欧洲另类| 久久免费观看视频| 国产精品一二三| 亚洲国产综合在线| 久久久99精品免费观看不卡| 亚洲国产精品久久久久婷婷老年| 亚洲一级特黄| 欧美日韩国产在线播放| 1024亚洲| 免费在线观看一区二区| 亚洲欧美日韩国产中文| 欧美视频一区二区在线观看| 亚洲国产影院| 欧美jizz19性欧美| 久久精品国产久精国产一老狼| 欧美调教vk| 日韩视频在线一区二区三区| 欧美aa在线视频| 久久久成人网| 伊人久久大香线蕉综合热线| 久久久久在线| 欧美永久精品| 国产精品国产馆在线真实露脸 | 欧美综合国产精品久久丁香| 亚洲国产免费| 欧美日韩a区| 在线亚洲自拍| 9人人澡人人爽人人精品| 欧美日本精品| 亚洲欧美日韩一区二区三区在线观看| 亚洲美女少妇无套啪啪呻吟| 欧美日韩亚洲一区在线观看| 亚洲视频一区二区免费在线观看| 亚洲精品永久免费精品| 欧美午夜女人视频在线| 欧美一级在线亚洲天堂| 欧美在线一二三| 在线欧美小视频| 欧美超级免费视 在线| 免费亚洲电影在线观看| 亚洲毛片一区| 日韩亚洲成人av在线| 欧美午夜精品理论片a级大开眼界| 亚洲一区二区高清视频| 性欧美超级视频| 在线日韩欧美视频| 亚洲二区免费| 国产精品黄页免费高清在线观看| 欧美在线观看你懂的| 久久在线精品| 亚洲影院免费观看| 久久久99免费视频| 一区二区三区**美女毛片| 中文在线一区| 在线播放一区| 一本到高清视频免费精品| 国产亚洲精品一区二区| 亚洲激情视频网站| 国产小视频国产精品| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美三区美女| 美国三级日本三级久久99| 欧美日韩成人精品| 狂野欧美一区| 国产精品国色综合久久| 欧美激情亚洲自拍| 国产欧美日韩一区| 最新国产の精品合集bt伙计| 国产精品久久久久久久久久直播 | 精品动漫3d一区二区三区| 日韩一区二区精品葵司在线| 国产美女精品人人做人人爽| 欧美成人免费在线视频| 国产精品毛片| 99国产精品久久久久久久久久| 国模私拍视频一区| 在线亚洲高清视频| 亚洲精选成人| 久久久久国内| 午夜一级久久| 欧美视频在线一区二区三区| 亚洲国产乱码最新视频 | 午夜精品久久| 欧美日韩亚洲一区二| 亚洲国产成人在线播放| 亚洲日本无吗高清不卡| 亚洲欧美另类国产| 午夜精品视频| 蜜桃av综合| 亚洲欧美另类国产| 国际精品欧美精品| 亚洲黑丝在线| 亚洲国产精品99久久久久久久久| 久久米奇亚洲| 国产久一道中文一区| 欧美专区中文字幕| 日韩亚洲精品电影| 牛牛国产精品| 午夜亚洲影视| 免费观看在线综合| 蜜桃久久精品乱码一区二区| 在线亚洲伦理| 久久久久88色偷偷免费| 久久免费视频这里只有精品| 国产伦精品一区二区三区免费| 亚洲区在线播放| 在线播放不卡| 亚洲欧美中文字幕| 午夜欧美不卡精品aaaaa| 欧美三级免费| 亚洲一区二区三区免费观看 | 性欧美1819sex性高清| 亚洲欧美日韩在线观看a三区| 欧美日韩喷水| 亚洲中无吗在线| 久久全国免费视频| 狠狠入ady亚洲精品经典电影| 亚洲一区在线直播| 狂野欧美激情性xxxx| 最新亚洲一区| 国产精品嫩草影院av蜜臀| 亚洲欧美大片| 欧美多人爱爱视频网站| 一区二区免费在线播放| 国产精品久久久久久久久久久久久| 亚洲一区二区精品视频| 免费观看日韩| 99精品热视频只有精品10| 国产精品成av人在线视午夜片| 亚洲一区在线看| 亚洲国产裸拍裸体视频在线观看乱了中文| 日韩午夜黄色| 国产欧美一区二区色老头| 久久亚洲精品欧美| 亚洲一级片在线看| 久久只精品国产| 欧美日韩一区在线视频| 亚洲视频一二三| 麻豆成人在线| 一区二区三区国产在线| 亚洲丰满少妇videoshd| 欧美视频在线播放| 欧美在线观看视频一区二区三区| 欧美成人亚洲成人日韩成人| 亚洲欧美日韩久久精品| 亚洲国产精品ⅴa在线观看| 欧美涩涩网站| 久久夜色精品国产亚洲aⅴ| 亚洲主播在线观看| 亚洲激情第一页| 久久精品官网| 一本久道久久综合中文字幕| 国产一区二区电影在线观看| 欧美视频在线观看 亚洲欧| 久久中文字幕导航| 午夜精品久久|