欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

了解多線程并深入分析CreateThread與_beginthreadex本質(zhì)區(qū)別

C語(yǔ)言專家集中營(yíng) ? 2018-01-09 17:08 ? 次閱讀

本文將帶領(lǐng)你與多線程作第一次親密接觸,并深入分析CreateThread與_beginthreadex的本質(zhì)區(qū)別,相信閱讀本文后你能輕松的使用多線程并能流暢準(zhǔn)確的回答CreateThread與_beginthreadex到底有什么區(qū)別,在實(shí)際的編程中到底應(yīng)該使用CreateThread還是_beginthreadex?

使用多線程其實(shí)是非常容易的,下面這個(gè)程序的主線程會(huì)創(chuàng)建了一個(gè)子線程并等待其運(yùn)行完畢,子線程就輸出它的線程ID號(hào)然后輸出一句經(jīng)典名言——Hello World。整個(gè)程序的代碼非常簡(jiǎn)短,只有區(qū)區(qū)幾行。

[cpp]view plaincopy

//最簡(jiǎn)單的創(chuàng)建多線程實(shí)例

#include

#include

//子線程函數(shù)

DWORDWINAPIThreadFun(LPVOIDpM)

{

printf("子線程的線程ID號(hào)為:%d\n子線程輸出HelloWorld\n",GetCurrentThreadId());

return0;

}

//主函數(shù),所謂主函數(shù)其實(shí)就是主線程執(zhí)行的函數(shù)。

intmain()

{

printf("最簡(jiǎn)單的創(chuàng)建多線程實(shí)例\n");

printf("--byMoreWindows(http://blog.csdn.net/MoreWindows)--\n\n");

HANDLEhandle=CreateThread(NULL,0,ThreadFun,NULL,0,NULL);

WaitForSingleObject(handle,INFINITE);

return0;

}

運(yùn)行結(jié)果如下所示:

了解多線程并深入分析CreateThread與_beginthreadex本質(zhì)區(qū)別

下面來(lái)細(xì)講下代碼中的一些函數(shù)

第一個(gè)CreateThread

函數(shù)功能:創(chuàng)建線程

函數(shù)原型:

HANDLEWINAPICreateThread(

LPSECURITY_ATTRIBUTESlpThreadAttributes,

SIZE_TdwStackSize,

LPTHREAD_START_ROUTINElpStartAddress,

LPVOIDlpParameter,

DWORDdwCreationFlags,

LPDWORDlpThreadId

);

函數(shù)說(shuō)明:

第一個(gè)參數(shù)表示線程內(nèi)核對(duì)象的安全屬性,一般傳入NULL表示使用默認(rèn)設(shè)置。

第二個(gè)參數(shù)表示線程棧空間大小。傳入0表示使用默認(rèn)大?。?MB)。

第三個(gè)參數(shù)表示新線程所執(zhí)行的線程函數(shù)地址,多個(gè)線程可以使用同一個(gè)函數(shù)地址。

第四個(gè)參數(shù)是傳給線程函數(shù)的參數(shù)。

第五個(gè)參數(shù)指定額外的標(biāo)志來(lái)控制線程的創(chuàng)建,為0表示線程創(chuàng)建之后立即就可以進(jìn)行調(diào)度,如果為CREATE_SUSPENDED則表示線程創(chuàng)建后暫停運(yùn)行,這樣它就無(wú)法調(diào)度,直到調(diào)用ResumeThread()。

第六個(gè)參數(shù)將返回線程的ID號(hào),傳入NULL表示不需要返回該線程ID號(hào)。

函數(shù)返回值:

成功返回新線程的句柄,失敗返回NULL。

第二個(gè)WaitForSingleObject

函數(shù)功能:等待函數(shù)–使線程進(jìn)入等待狀態(tài),直到指定的內(nèi)核對(duì)象被觸發(fā)。

函數(shù)原形:

DWORDWINAPIWaitForSingleObject(

HANDLEhHandle,

DWORDdwMilliseconds

);

函數(shù)說(shuō)明:

第一個(gè)參數(shù)為要等待的內(nèi)核對(duì)象。

第二個(gè)參數(shù)為最長(zhǎng)等待的時(shí)間,以毫秒為單位,如傳入5000就表示5秒,傳入0就立即返回,傳入INFINITE表示無(wú)限等待。

因?yàn)榫€程的句柄在線程運(yùn)行時(shí)是未觸發(fā)的,線程結(jié)束運(yùn)行,句柄處于觸發(fā)狀態(tài)。所以可以用WaitForSingleObject()來(lái)等待一個(gè)線程結(jié)束運(yùn)行。

函數(shù)返回值:

在指定的時(shí)間內(nèi)對(duì)象被觸發(fā),函數(shù)返回WAIT_OBJECT_0。超過(guò)最長(zhǎng)等待時(shí)間對(duì)象仍未被觸發(fā)返回WAIT_TIMEOUT。傳入?yún)?shù)有錯(cuò)誤將返回WAIT_FAILED

CreateThread()函數(shù)是Windows提供的API接口,在C/C++語(yǔ)言另有一個(gè)創(chuàng)建線程的函數(shù)_beginthreadex(),在很多書上(包括《Windows核心編程》)提到過(guò)盡量使用_beginthreadex()來(lái)代替使用CreateThread(),這是為什么了?下面就來(lái)探索與發(fā)現(xiàn)它們的區(qū)別吧。

首先要從標(biāo)準(zhǔn)C運(yùn)行庫(kù)與多線程的矛盾說(shuō)起,標(biāo)準(zhǔn)C運(yùn)行庫(kù)在1970年被實(shí)現(xiàn)了,由于當(dāng)時(shí)沒(méi)任何一個(gè)操作系統(tǒng)提供對(duì)多線程的支持。因此編寫標(biāo)準(zhǔn)C運(yùn)行庫(kù)的程序員根本沒(méi)考慮多線程程序使用標(biāo)準(zhǔn)C運(yùn)行庫(kù)的情況。比如標(biāo)準(zhǔn)C運(yùn)行庫(kù)的全局變量errno。很多運(yùn)行庫(kù)中的函數(shù)在出錯(cuò)時(shí)會(huì)將錯(cuò)誤代號(hào)賦值給這個(gè)全局變量,這樣可以方便調(diào)試。但如果有這樣的一個(gè)代碼片段:

[cpp]view plaincopy

if(system("notepad.exereadme.txt")==-1)

{

switch(errno)

{

...//錯(cuò)誤處理代碼

}

}

假設(shè)某個(gè)線程A在執(zhí)行上面的代碼,該線程在調(diào)用system()之后且尚未調(diào)用switch()語(yǔ)句時(shí)另外一個(gè)線程B啟動(dòng)了,這個(gè)線程B也調(diào)用了標(biāo)準(zhǔn)C運(yùn)行庫(kù)的函數(shù),不幸的是這個(gè)函數(shù)執(zhí)行出錯(cuò)了并將錯(cuò)誤代號(hào)寫入全局變量errno中。這樣線程A一旦開始執(zhí)行switch()語(yǔ)句時(shí),它將訪問(wèn)一個(gè)被B線程改動(dòng)了的errno。這種情況必須要加以避免!因?yàn)椴粏螁问沁@一個(gè)變量會(huì)出問(wèn)題,其它像strerror()、strtok()、tmpnam()、gmtime()、asctime()等函數(shù)也會(huì)遇到這種由多個(gè)線程訪問(wèn)修改導(dǎo)致的數(shù)據(jù)覆蓋問(wèn)題。

為了解決這個(gè)問(wèn)題,Windows操作系統(tǒng)提供了這樣的一種解決方案——每個(gè)線程都將擁有自己專用的一塊內(nèi)存區(qū)域來(lái)供標(biāo)準(zhǔn)C運(yùn)行庫(kù)中所有有需要的函數(shù)使用。而且這塊內(nèi)存區(qū)域的創(chuàng)建就是由C/C++運(yùn)行庫(kù)函數(shù)_beginthreadex()來(lái)負(fù)責(zé)的。下面列出_beginthreadex()函數(shù)的源代碼(我在這份代碼中增加了一些注釋)以便讀者更好的理解_beginthreadex()函數(shù)與CreateThread()函數(shù)的區(qū)別。

[cpp]view plaincopy

//_beginthreadex源碼整理ByMoreWindows(http://blog.csdn.net/MoreWindows)

_MCRTIMPuintptr_t__cdecl_beginthreadex(

void*security,

unsignedstacksize,

unsigned(__CLR_OR_STD_CALL*initialcode)(void*),

void*argument,

unsignedcreateflag,

unsigned*thrdaddr

)

{

_ptiddataptd;//pointertoper-threaddata見(jiàn)注1

uintptr_tthdl;//threadhandle線程句柄

unsignedlongerr=0L;//ReturnfromGetLastError()

unsigneddummyid;//dummyreturnedthreadID線程ID號(hào)

//validationsection檢查initialcode是否為NULL

_VALIDATE_RETURN(initialcode!=NULL,EINVAL,0);

//InitializeFlsGetValuefunctionpointer

__set_flsgetvalue();

//Allocateandinitializeaper-threaddatastructurefortheto-be-createdthread.

//相當(dāng)于new一個(gè)_tiddata結(jié)構(gòu),并賦給_ptiddata指針。

if((ptd=(_ptiddata)_calloc_crt(1,sizeof(struct_tiddata)))==NULL)

gotoerror_return;

//Initializetheper-threaddata

//初始化線程的_tiddata塊即CRT數(shù)據(jù)區(qū)域見(jiàn)注2

_initptd(ptd,_getptd()->ptlocinfo);

//設(shè)置_tiddata結(jié)構(gòu)中的其它數(shù)據(jù),這樣這塊_tiddata塊就與線程聯(lián)系在一起了。

ptd->_initaddr=(void*)initialcode;//線程函數(shù)地址

ptd->_initarg=argument;//傳入的線程參數(shù)

ptd->_thandle=(uintptr_t)(-1);

#ifdefined(_M_CEE)||defined(MRTDLL)

if(!_getdomain(&(ptd->__initDomain)))//見(jiàn)注3

{

gotoerror_return;

}

#endif//defined(_M_CEE)||defined(MRTDLL)

//Makesurenon-NULLthrdaddrispassedtoCreateThread

if(thrdaddr==NULL)//判斷是否需要返回線程ID號(hào)

thrdaddr=&dummyid;

//Createthenewthreadusingtheparameterssuppliedbythecaller.

//_beginthreadex()最終還是會(huì)調(diào)用CreateThread()來(lái)向系統(tǒng)申請(qǐng)創(chuàng)建線程

if((thdl=(uintptr_t)CreateThread(

(LPSECURITY_ATTRIBUTES)security,

stacksize,

_threadstartex,

(LPVOID)ptd,

createflag,

(LPDWORD)thrdaddr))

==(uintptr_t)0)

{

err=GetLastError();

gotoerror_return;

}

//Goodreturn

return(thdl);//線程創(chuàng)建成功,返回新線程的句柄.

//Errorreturn

error_return:

//EitherptdisNULL,oritpointstotheno-longer-necessaryblock

//calloc-edforthe_tiddatastructwhichshouldnowbefreedup.

//回收由_calloc_crt()申請(qǐng)的_tiddata塊

_free_crt(ptd);

//Maptheerror,ifnecessary.

//Note:thisroutinereturns0forfailure,justliketheWin32

//APICreateThread,but_beginthread()returns-1forfailure.

//校正錯(cuò)誤代號(hào)(可以調(diào)用GetLastError()得到錯(cuò)誤代號(hào))

if(err!=0L)

_dosmaperr(err);

return((uintptr_t)0);//返回值為NULL的效句柄

}

講解下部分代碼:

注1._ptiddataptd;中的_ptiddata是個(gè)結(jié)構(gòu)體指針。在mtdll.h文件被定義:

typedefstruct_tiddata*_ptiddata

微軟對(duì)它的注釋為Structure for each thread's data。這是一個(gè)非常大的結(jié)構(gòu)體,有很多成員。本文由于篇幅所限就不列出來(lái)了。

注2._initptd(ptd,_getptd()->ptlocinfo);微軟對(duì)這一句代碼中的getptd()的說(shuō)明為:

/* return address of per-thread CRT data */

_ptiddata__cdecl_getptd(void);

對(duì)_initptd()說(shuō)明如下:

/* initialize a per-thread CRT data block */

void__cdecl_initptd(_Inout_ _ptiddata_Ptd,_In_opt_ pthreadlocinfo_Locale);

注釋中的CRT(C Runtime Library)即標(biāo)準(zhǔn)C運(yùn)行庫(kù)。

注3.if(!_getdomain(&(ptd->__initDomain)))中的_getdomain()函數(shù)代碼可以在thread.c文件中找到,其主要功能是初始化COM環(huán)境。

由上面的源代碼可知,_beginthreadex()函數(shù)在創(chuàng)建新線程時(shí)會(huì)分配并初始化一個(gè)_tiddata塊。這個(gè)_tiddata塊自然是用來(lái)存放一些需要線程獨(dú)享的數(shù)據(jù)。事實(shí)上新線程運(yùn)行時(shí)會(huì)首先將_tiddata塊與自己進(jìn)一步關(guān)聯(lián)起來(lái)。然后新線程調(diào)用標(biāo)準(zhǔn)C運(yùn)行庫(kù)函數(shù)如strtok()時(shí)就會(huì)先取得_tiddata塊的地址再將需要保護(hù)的數(shù)據(jù)存入_tiddata塊中。這樣每個(gè)線程就只會(huì)訪問(wèn)和修改自己的數(shù)據(jù)而不會(huì)去篡改其它線程的數(shù)據(jù)了。因此,如果在代碼中有使用標(biāo)準(zhǔn)C運(yùn)行庫(kù)中的函數(shù)時(shí),盡量使用_beginthreadex()來(lái)代替CreateThread()。相信閱讀到這里時(shí),你會(huì)對(duì)這句簡(jiǎn)短的話有個(gè)非常深刻的印象,如果有面試官問(wèn)起,你也可以流暢準(zhǔn)確的回答了^_^。

接下來(lái),類似于上面的程序用CreateThread()創(chuàng)建輸出“Hello World”的子線程,下面使用_beginthreadex()來(lái)創(chuàng)建多個(gè)子線程:

[cpp]view plaincopy

//創(chuàng)建多子個(gè)線程實(shí)例

#include

#include

#include

//子線程函數(shù)

unsignedint__stdcallThreadFun(PVOIDpM)

{

printf("線程ID號(hào)為%4d的子線程說(shuō):HelloWorld\n",GetCurrentThreadId());

return0;

}

//主函數(shù),所謂主函數(shù)其實(shí)就是主線程執(zhí)行的函數(shù)。

intmain()

{

printf("創(chuàng)建多個(gè)子線程實(shí)例\n");

printf("--byMoreWindows(http://blog.csdn.net/MoreWindows)--\n\n");

constintTHREAD_NUM=5;

HANDLEhandle[THREAD_NUM];

for(inti=0;i

handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,NULL);

WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);

return0;

}

運(yùn)行結(jié)果如下:

了解多線程并深入分析CreateThread與_beginthreadex本質(zhì)區(qū)別

圖中每個(gè)子線程說(shuō)的都是同一句話,不太好看。能不能來(lái)一個(gè)線程報(bào)數(shù)功能,即第一個(gè)子線程輸出1,第二個(gè)子線程輸出2,第三個(gè)子線程輸出3,……。要實(shí)現(xiàn)這個(gè)功能似乎非常簡(jiǎn)單——每個(gè)子線程對(duì)一個(gè)全局變量進(jìn)行遞增并輸出就可以了。代碼如下:

[cpp]view plaincopy

//子線程報(bào)數(shù)

#include

#include

#include

intg_nCount;

//子線程函數(shù)

unsignedint__stdcallThreadFun(PVOIDpM)

{

g_nCount++;

printf("線程ID號(hào)為%4d的子線程報(bào)數(shù)%d\n",GetCurrentThreadId(),g_nCount);

return0;

}

//主函數(shù),所謂主函數(shù)其實(shí)就是主線程執(zhí)行的函數(shù)。

intmain()

{

printf("子線程報(bào)數(shù)\n");

printf("--byMoreWindows(http://blog.csdn.net/MoreWindows)--\n\n");

constintTHREAD_NUM=10;

HANDLEhandle[THREAD_NUM];

g_nCount=0;

for(inti=0;i

handle[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,NULL);

WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);

return0;

}

對(duì)一次運(yùn)行結(jié)果截圖如下:

了解多線程并深入分析CreateThread與_beginthreadex本質(zhì)區(qū)別

顯示結(jié)果從1數(shù)到10,看起來(lái)好象沒(méi)有問(wèn)題。

答案是不對(duì)的,雖然這種做法在邏輯上是正確的,但在多線程環(huán)境下這樣做是會(huì)產(chǎn)生嚴(yán)重的問(wèn)題。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7615

    瀏覽量

    137847
  • 多線程
    +關(guān)注

    關(guān)注

    0

    文章

    278

    瀏覽量

    20076

原文標(biāo)題:多線程CreateThread與_beginthreadex本質(zhì)區(qū)別

文章出處:【微信號(hào):C_Expert,微信公眾號(hào):C語(yǔ)言專家集中營(yíng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    FPGA與ARM的本質(zhì)區(qū)別是什么?

    FPGA(Field-Programmable Gate Array)與ARM在多個(gè)方面存在本質(zhì)區(qū)別。 首先,從它們的定義和結(jié)構(gòu)上來(lái)看,F(xiàn)PGA是一種現(xiàn)場(chǎng)可編程門陣列,屬于可編程器件的一種。它的內(nèi)部
    發(fā)表于 04-28 08:56

    FPGA與ARM的本質(zhì)區(qū)別

    FPGA(Field-Programmable Gate Array)與ARM在多個(gè)方面存在本質(zhì)區(qū)別。 首先,從它們的定義和結(jié)構(gòu)上來(lái)看,F(xiàn)PGA是一種現(xiàn)場(chǎng)可編程門陣列,屬于可編程器件的一種。它的內(nèi)部
    發(fā)表于 04-28 09:00

    uCOS任務(wù)堆棧的深入分析(轉(zhuǎn))

    uCOS任務(wù)堆棧的深入分析(轉(zhuǎn))
    發(fā)表于 08-24 23:30

    PLC與單片機(jī)的本質(zhì)區(qū)別

    PLC與單片機(jī)的本質(zhì)區(qū)別是什么?
    發(fā)表于 01-13 07:55

    多線程和多進(jìn)程的區(qū)別

    6.你的數(shù)據(jù)庫(kù)一會(huì)又500個(gè)連接數(shù),一會(huì)有10個(gè),你分析一下情況7.udp和tcp的區(qū)別8.多線程和多進(jìn)程的區(qū)別9.有一臺(tái)web服務(wù)器,你選擇用多線
    發(fā)表于 07-19 07:21

    請(qǐng)問(wèn)PLC與單片機(jī)的本質(zhì)區(qū)別在哪里?

    PLC與單片機(jī)的本質(zhì)區(qū)別在哪里?
    發(fā)表于 11-09 06:04

    筆記本的結(jié)構(gòu)深入分析

    筆記本的結(jié)構(gòu)深入分析  電腦技術(shù)的應(yīng)用為我們的生活和工作帶來(lái)了巨大改變,使我們的生活學(xué)習(xí)工作有了質(zhì)的轉(zhuǎn)變。普通的用戶對(duì)電腦的了解
    發(fā)表于 01-21 15:53 ?4323次閱讀

    基于SWT的多線程解決方案

    介紹了在基于 SWT 的C / S 結(jié)構(gòu)的項(xiàng)目開發(fā)中,當(dāng)用UI 主線程進(jìn)行后臺(tái)數(shù)據(jù)讀取或交換時(shí)導(dǎo)致的UI 線程堵塞現(xiàn)象的解決方案。通過(guò)對(duì)UI 線程深入了解,利用
    發(fā)表于 06-07 17:08 ?0次下載

    多核與多線程技術(shù)的區(qū)別

    毫無(wú)疑問(wèn)的,多核、多線程此二詞已快成為當(dāng)今處理器架構(gòu)設(shè)計(jì)中的兩大顯學(xué),如同歷史戰(zhàn)國(guó)時(shí)代以儒、墨兩大派的顯學(xué),只不過(guò)當(dāng)年兩大治世思想學(xué)派是爭(zhēng)得你死我亡,而多核、多線程則是相互兼容蓄,今日幾乎任何
    發(fā)表于 10-19 16:26 ?0次下載

    多線程好還是單線程好?單線程多線程區(qū)別 優(yōu)缺點(diǎn)分析

    摘要:如今單線程多線程已經(jīng)得到普遍運(yùn)用,那么到底多線程好還是單線程好呢?單線程多線程
    發(fā)表于 12-08 09:33 ?8.2w次閱讀

    光纖和光纜的本質(zhì)區(qū)別是什么

    相信大家都聽(tīng)過(guò)光纖盒光纜,那光纖和光纜一樣嗎?本質(zhì)區(qū)別在哪里?科蘭綜合布線小編指出:其實(shí)兩者都是一種傳輸介質(zhì)。但嚴(yán)格意義上講,兩者是不相同的產(chǎn)品,下面一起來(lái)了解一下兩者區(qū)別
    發(fā)表于 03-23 10:24 ?6363次閱讀

    分析unidbg(unidbgMutil)多線程機(jī)制

    由于在工作中遇到了某翻譯so中有多線程調(diào)用,因此使用unidbg分析(基于unidbgMutilThread)增加阻塞喚醒機(jī)制(futex系統(tǒng)調(diào)用),但仍未調(diào)用成功
    的頭像 發(fā)表于 05-20 17:23 ?3063次閱讀
    <b class='flag-5'>分析</b>unidbg(unidbgMutil)<b class='flag-5'>多線程</b>機(jī)制

    線程是什么的基本單位 進(jìn)程與線程本質(zhì)區(qū)別

    的代碼、數(shù)據(jù)以及用于執(zhí)行這些代碼的上下文信息。一個(gè)進(jìn)程可以由一個(gè)或多個(gè)線程組成,從而并發(fā)執(zhí)行多個(gè)任務(wù)。 本質(zhì)區(qū)別: 資源擁有方式:進(jìn)程是資源分配的基本單位,每個(gè)進(jìn)程擁有獨(dú)立的內(nèi)存空間、文件描述符、頁(yè)面表等資源,之
    的頭像 發(fā)表于 02-02 16:30 ?1024次閱讀

    聚徽觸控-工控機(jī)和商用電腦本質(zhì)區(qū)別是什么

    工控機(jī)和商用電腦在多個(gè)方面存在本質(zhì)區(qū)別,具體如下:
    的頭像 發(fā)表于 07-16 09:19 ?360次閱讀

    Python中多線程和多進(jìn)程的區(qū)別

    Python作為一種高級(jí)編程語(yǔ)言,提供了多種并發(fā)編程的方式,其中多線程與多進(jìn)程是最常見(jiàn)的兩種方式之一。在本文中,我們將探討Python中多線程與多進(jìn)程的概念、區(qū)別以及如何使用線程池與進(jìn)
    的頭像 發(fā)表于 10-23 11:48 ?503次閱讀
    Python中<b class='flag-5'>多線程</b>和多進(jìn)程的<b class='flag-5'>區(qū)別</b>