日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程编程的一点小心得(1)

發布時間:2023/12/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程编程的一点小心得(1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近有了很多想法,想把我用過的東西都吃透,這樣才不會變成所謂的“樣樣通樣樣松”。我是新手,老鳥請飄過,當然,這篇小心得如果有什么毛病,還請指出來。先行謝過!

其實我本來想把博客當作自己的日記,記錄下學習的點點滴滴,寫下的就代表是學會的東西,人家說好記性不如爛筆頭嘛。

一直以來對多線程這塊就迷迷糊糊的,用得不太多,即便是用了,也是把以前寫的代碼拿出來,稍微修改一下,就適應了新的需求。也看過一些資料,但都沒實踐過,所以就馬馬虎虎地,能夠適應工作需求就得過且過。其實這種思想是非常錯誤的。做技術一定要踏實,否則就無法成長。

閑話少說書歸正傳,接下來的幾篇就把多線程的東西學習、總結一下。先上一段萬金油:
線程:有時被稱為輕量級進程(Lightweight Process,LWP),是程序執行流的最小單元。一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。一個線程可以創建和撤消另一個線程,同一進程中的多個線程之間可以并發執行。由于線程之間的相互制約,致使線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。每一個程序都至少有一個線程,那就是程序本身。

自從有了線程,這個世界就變得吵起來了,線程的周期、調度與優先級、資源共享、線程同步、守護線程、死鎖、信號量。。后面咱們再慢慢研究這些東西吧,今天先來簡單明白線程到底是什么,怎么應用在編程中。

老慣例,上個程序吧。建立一個標準的基于對話框的MFC程序,拖一個edit控件和一個button在上面,資源命名分別為ID_EDIT_NUMBER和ID_BUTTON_START。給edit控件關聯一個變量CEdit * m_editNumber。弄差不多這個樣子就行。

?先寫一個線程函數,告訴電腦在這個線程里要做什么。

  • DWORD?_stdcall?ThreadProc(LPVOID?lpParameter)?
  • {?
  • ????CMultithreadTestDlg?*?dlg?=?(CMultithreadTestDlg*)?lpParameter;?
  • ????CString?szCounter;?
  • ?
  • ????for(int?i?=?0;?i?<?10000;?i++)?
  • ????{?
  • ????????szCounter.Format(_T("%d"),?i);?
  • ????????dlg->m_editNumber.SetWindowTextW(szCounter);?
  • ????????szCounter.ReleaseBuffer();?
  • ????}?
  • ?
  • ????return?0;?
  • }?
  • 很簡單,就是讓edit控件顯示不停增加的數字。?

    接下來就要想辦法啟動這個線程。

    在CMultithreadTestDlg中添加一個成員變量HANDLE m_hThread。雙擊start按鈕,編寫按鈕的單擊事件。

  • void?CMultithreadTestDlg::OnBnClickedButtonStart()?
  • {?
  • ????//?TODO:?Add?your?control?notification?handler?code?here?
  • ????m_hThread?=?CreateThread(NULL,?0,?ThreadProc,?this,?0,?NULL);?
  • }?
  • CreateThread函數的原型如下:

  • HANDLE?WINAPI?CreateThread(?
  • ??__in_opt???LPSECURITY_ATTRIBUTES?lpThreadAttributes,?
  • ??__in???????SIZE_T?dwStackSize,?
  • ??__in???????LPTHREAD_START_ROUTINE?lpStartAddress,?
  • ??__in_opt???LPVOID?lpParameter,?
  • ??__in???????DWORD?dwCreationFlags,?
  • ??__out_opt??LPDWORD?lpThreadId?
  • );?
  • 第一個參數是安全屬性,指向一個LPSECURITY_ATTRIBUTES類型的結構體,一般設為NULL;

    第二個參數是線程的堆棧大小,如果不是內存特別緊張的話,就設為0,表示windows將動態調整堆棧的大小;

    第三個參數是指向線程函數的指針,其實就是函數名。函數名隨便起,但是在聲名函數時必須要遵守形式

  • DWORD?WINAPI?ThreadProc(LPVOID?lpParameter)??
  • 否則就無法成功調用;

    第四個參數是向線程函數傳遞的參數,不傳遞時就設為NULL;

    第五個參數是線程標志,有兩個可取值:

    ? ? ?1). CREATE_SUSPENDED,表示創建后立即掛起

    ? ? ?2). 0,表示正常創建,創建后立刻運行

    第六個參數用來保存新建線程的ID,如果不需要處理線程ID的話,則可傳入NULL。

    返回值是線程的句柄。

    運行時效果如下

    這個程序其實是有風險的,風險有二:

    ? ? 1). 在MFC程序中,應該盡量使用AfxBeginThread方法來創建線程。

    ? ? 2). 如果我不停地按start,一會內存就用光了=。=

    2的解決方法就不上了,無非是使用標志位,線程沒跑完之前不再創建新的線程。

    來說說AfxBeginThread。這是MFC中的比較安全的線程創建方法。函數原型如下:

  • CWinThread*?AfxBeginThread(?
  • ???AFX_THREADPROC?pfnThreadProc,?
  • ???LPVOID?pParam,?
  • ???int?nPriority?=?THREAD_PRIORITY_NORMAL,?
  • ???UINT?nStackSize?=?0,?
  • ???DWORD?dwCreateFlags?=?0,?
  • ???LPSECURITY_ATTRIBUTES?lpSecurityAttrs?=?NULL??
  • );?
  • CWinThread*?AfxBeginThread(?
  • ???CRuntimeClass*?pThreadClass,?
  • ???int?nPriority?=?THREAD_PRIORITY_NORMAL,?
  • ???UINT?nStackSize?=?0,?
  • ???DWORD?dwCreateFlags?=?0,?
  • ???LPSECURITY_ATTRIBUTES?lpSecurityAttrs?=?NULL??
  • );?
  • 有兩個可以重載的函數,常用的是第一個。也能看出來,第一個函數與CreateThread()的參數其實是差不多的,只不過順序不太一樣。需要注意的是第二個重載函數,參數一是CRuntimeClass * pThreadClass,CRuntimeClass是個結構體,MSDN里的解釋是“The RUNTIME_CLASS of an object derived from CWinThread.”為此我特意看了一下AfxBeginThread的源代碼,其中有如下一行:

  • ASSERT(pThreadClass->IsDerivedFrom(RUNTIME_CLASS(CWinThread)));?
  • 表明RUNTIME_CLASS是個宏定義。

  • #define?RUNTIME_CLASS(class_name)?(class_name::GetThisClass())?
  • 也就是用這個宏將線程類指針轉換為指向CRuntimeClass的對象指針。

    那么新的線程創建語句就變為了:

  • CWinThread?*?m_thread;? // m_thread為成員變量
  • m_thread?=?AfxBeginThread(ThreadProc,?this);?
  • 而且需要將線程函數的聲明修改一下:

  • UINT?ThreadProc(LPVOID?lpParameter)?
  • 線程執行的中間是可以暫停的,使用DWORD CWinThread::SuspendThread()函數即可。暫停后可以使用DWORD?CWinThread::ResumeThread()函數使線程恢復運行。

    這是基本用法,至于一些高級點兒的東西,明兒繼續。

    PS:正所謂懂得越多就發現懂得越少,今×××資料,又搜出好多沒聽過的東西=。=,全部記在本子上,逐個消滅之。。

    PSS:下一個目標,看明白與這個網頁相關聯的東西。。http://en.wikipedia.org/wiki/Thread_(computing)

    PSSS:這玩意兒真形象。。

    ?

    轉載于:https://blog.51cto.com/serious/857669

    總結

    以上是生活随笔為你收集整理的多线程编程的一点小心得(1)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。