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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

跨平台多线程编程

發布時間:2023/12/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 跨平台多线程编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
多線程介紹 ? POSIX 1003.1-2001?定義了多線程編程的標準API。這個API就是廣為人知的pthreads。它的目的在于為跨平臺編寫多線程程序提供便利。 ? 多線程程序的編寫 ? 本文介紹了Linux 和 WIN32 平臺下的多線程程序的編寫方法 ? Linux 系統對 pthreads 提供了良好的支持。一般地安裝完Linux系統后在/usr/include目錄下包含了 pthreads 的頭文件。在 /usr/lib 下面包含了pthread 的庫文件:libpthread.a 和 libpthread.so。其中libpthread.a 為靜態鏈接庫,libpthread.so為動態連接庫。 ? WIN32 threads 線程庫并不直接支持 pthreads,因此網絡上出現了POSIX Threads for Win32 的開源項目,為 WIN32 下開發 Pthreads 多線程程序提供了方便。Pthreads for win32 的下載地址為:ftp://sourceware.org/pub/pthreads-win32。最新版本為 2-8-10。下載pthreads-w32-2-8-0-release.exe 后運行解壓出三個目錄:pre-build.2 pthreads.2 和QueueUserAPCEx。Pthreads.2 里面包含了pthreads 的源代碼,我們主要關心pre-build.2 這個目錄。Pre-build.2 里面包含了include和 lib 分別包含了pthreads for win32 的頭文件和庫文件(包括動態連接庫)。將include 和lib 里面的內容分別復制到你的編譯器的include 和?lib?目錄,同時將lib 目錄中的 dll 文件copy 到操作系統的system32 文件夾中。 ? ? ? 為了保證platform-independent, 很好的一個方法就是使用3rd-party的library, 呵呵.?
??? official site:?http://sourceware.org/pthreads-win32/.?
??? source code:?ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.tar.gz

1. 編譯:?
??? 雖然源碼包里提供了vc6的項目文件, 但是打不開的, 只能用nmake. 默認的會告訴你一堆nmake參數的.?
??? 我所要用的是編譯成static的library, 所以輸入"nmake clean VC-static", 編譯很快的. 不過默認會鏈接到VC的crt, 我們需要修改它的makefile. 找到CFLAGS那一行, 把"/MD"改成"/MT".?

2. 項目:?
??? 誒.. 有好多地方要改的.?
??? a) 當然是vs路徑的include啊, lib啊.. 自己加.?
??? b) 項目的crt設置成"/MT"和"/MTd". 額外的lib加: pthreadVC2(d).lib ws2_32.lib
??? c) preprocesser定義的地方, 加一個“PTW32_STATIC_LIB”宏, 不然link的時候會找不到symbol的.?
??? d) 好了, 你可以coding了, 隨便pthread_create()一把吧.?

3. 編碼:?
??? 嗯嗯.. 如果真的直接pthread_create()的話可是會access violation的呀. win32下的線程很詭異的, 像winsock一樣, 調用任何其它函數之前必須調用pthread_win32_process_attach_np(), 結束后必須調用pthread_win32_process_detach_np(). 代碼大概就是這樣的:?

int?main()

{

#ifdef?WIN32

#ifdef?PTW32_STATIC_LIB

????pthread_win32_process_attach_np();

#endif

#endif

????/* do something with pthread library */

#ifdef?WIN32

#ifdef?PTW32_STATIC_LIB

????pthread_win32_process_detach_np();

#endif

#endif

}


??? 額.. *nix下應該不會有人sb到用static link吧.. 我可不知道怎樣弄的. 下面是一個完整的例子:?

#include?<stdio.h>

#include?<stdlib.h>

#include?<pthread.h>

?

pthread_mutex_t????count_mutex??? ??? =?PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_t????condition_mutex?=?PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t????condition_cond? =?PTHREAD_COND_INITIALIZER;

?

void?*functionCount1(void*?param);

void?*functionCount2(void*?param);

int?count?= 0;

#define?COUNT_DONE??? 10

#define?COUNT_HALT1??? 3

#define?COUNT_HALT2??? 6

?

int?main()

{

#ifdef?WIN32

#ifdef?PTW32_STATIC_LIB

????pthread_win32_process_attach_np();

#endif

#endif

?

????pthread_t?thread1,?thread2;

????pthread_create(&thread1, 0,?functionCount1, 0);

????pthread_create(&thread2, 0,?functionCount2, 0);

????pthread_join(thread1, 0);

????pthread_join(thread2, 0);

?

#ifdef?WIN32

#ifdef?PTW32_STATIC_LIB

????pthread_win32_process_detach_np();

#endif

#endif

????return?0;

}

?

void?*functionCount1(void*?param)

{

????for?(;;)

??? {

??? ????pthread_mutex_lock(&condition_mutex);

??? ????while?(count?>=?COUNT_HALT1?&&?count?<=?COUNT_HALT2)

??? ??? {

??? ??? ????pthread_cond_wait(&condition_cond, &condition_mutex);

??? ??? ????/* ... */

??? ??? }

??? ????pthread_mutex_unlock(&condition_mutex);

?

??? ????pthread_mutex_lock(&count_mutex);

??? ????count++;

??? ????printf("Counter value functionCount1: %d\n",?count);

??? ????pthread_mutex_unlock(&count_mutex);

?

??? ????if?(count?>=?COUNT_DONE)?return?0;

??? }

}

?

void?*functionCount2(void*?param)

{

????for?(;;)

??? {

??? ????pthread_mutex_lock(&condition_mutex);

??? ????if?(count?<?COUNT_HALT1?||?count?>?COUNT_HALT2)

??? ??? {

??? ??? ????pthread_cond_signal(&condition_cond);

??? ??? }

??? ????pthread_mutex_unlock(&condition_mutex);

?

??? ????pthread_mutex_lock(&count_mutex);

??? ????count++;

??? ????printf("Counter value functionCount2: %d\n",?count);

??? ????pthread_mutex_unlock(&count_mutex);

?

??? ????if?(count?>=?COUNT_DONE)?return?0;

??? }

}

??? 舉這個例子只是為了說明pthread_cond_signal()和pthread_cond_wait()的用法. 注意到區別了么, 一個用if來判斷, 一個用的則是while. 之所以要這樣是由于pthread_cond_wait()這個函數很特別, 在進入這個函數開始會先解鎖(即解mutex), 離開這個函數時再次加鎖, 中間會有空隙, 必須要再次判斷. 所以如果注釋的地方有代碼的話, 是不能保證正確性的. 具體可以man一下自己看.?

4. 參考:?
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
http://bbs.chinaunix.net/thread-1060780-1-1.html
? ======================================================================== ? 第一個多線程程序: ? 我們以最常見的helloworld 程序開始多線程之旅吧。代碼如下所示:?main.c? #include<pthread.h> void* thread_one(void* dummy) { ????? while(1) ????? { ?????????? printf("Hello,world.this is thread one\n"); ????? } ????? } ? void* thread_two(void* dummy) { ????? while(1) ????? { ?????????? printf("Hello,world.this is thread two\n"); ????? } ????? } ? int main(void) { ????? pthread_t tid[2]; ????? pthread_create(&tid[0],NULL,thread_one,NULL); ????? pthread_create(&tid[1],NULL,thread_two,NULL); ????? pthread_exit(NULL); } ? 編譯、鏈接: WIN32 VC中新建一個空的工程,加入上述代碼,在鏈接時記得加入pthreadVC2.lib。(在vc 中在“工程”->“設置”->“鏈接”中) ? LINUX: Gcc –o hello main.c –lpthread ? 運行程序就可以看到兩個線程在交互運行,不斷地出現各自打印的信息。 ? 從上面的程序看出,有了pthreads,開發跨平臺的多線程程序并不是難事。當然這里只是開始,后續的文章就詳細介紹?pthreads?的多線程開發。 ? ======================================================================================== (二) Pthreads 的API
在 pthreads 函數接口可以分為以下三類(關于函數的具體接口參考文章末尾):
1. 線程管理(thread management):用于線程創建、detach、join已經設置和查詢線程屬性的函數:主要函數有pthread_create,pthread_exit,pthread_detach,pthread_join。pthread_self
2. Mutex 操作函數:用來保證資源的互斥訪問,它用來實現多線程訪問數據時的同步機制。
主要函數有:pthread_mutex_init,pthread_mutex_lock,pthread_mutex_unlock
3.狀態變量操作函數: 這類函數用來建立共享mutex 的多線程通信。它根據程序員設定的條件來決定是否發出信號(signal)或者等待(wait)。主要函數有:pthread_cond_init,pthread_cond_signal: pthread_cond_wait。
?
在pthreads 常用的類型pthread_t 用來記錄每個線程的id。
?
下面開始對跨平臺多線程編程教程(一)中的例子進行說明。
?
第一行:#include <pthread.h> 包含了pthreads 中類型定義和函數接口。
pthread_t tid[2];? 用來存儲兩個線程的id
pthread_create(&tid[0],NULL,thread_one,NULL); 創建了第一個線程。這個線程開始執行thread_one 函數。
pthread_create(&tid[1],NULL,thread_two,NULL); 創建了第二個線程。這個線程開始執行thread_two 函數。
?
兩個線程都沒有傳遞參數(第四個參數為NULL)。開始執行后,線程間不斷地調度,交替地打印各自的字符串。
?
注意:在前面的例子的main函數的最后部分有調用了函數pthread_exit; 嘗試去掉這個語句再運行程序,你會發現兩個線程在打印了一些字符串后就退出了。原因是正常情況下,創建了兩個線程后,主線程調用 return 0 退出,它所創建的子線程也跟著退出。調用pthread_exit 后子線程就可以一直運行了。
?
后面的章節將對三類 pthreads API 進行相信的介紹。
?
pthreads 常用API 參考(源于網絡)
?
pthread_create(
?????????????? pthread_t *tid,
?????????????? const pthread_attr_t *attr,
?????????????? void*(*start_routine)(void*),
?????????????? void *arg
?????????????? );
用途:創建一個線程
//參數:tid 用于返回新創建線程的線程號;
//start_routine 是線程函數指針,線程從這個函數開始獨立地運行;
//arg 是傳遞給線程函數的參數。由于start_routine 是一個指向參數類型為void*,返回值為void*的指針,所以如果需要傳遞或返回多個參數時,可以使用強制類型轉化。
?
void pthread_exit(
??????????? void* value_ptr
???????????? );
用途:退出線程
參數:value_ptr 是一個指向返回狀態值的指針。
?
int pthread_join(
???????????? pthread_t tid ,
???????????? void **status
???????????? );
// 參數tid 是希望等待的線程的線程號,status 是指向線程返回值的指針,線程的返回值就是pthread_exit 中的value_ptr 參數,或者是return語句中的返回值。該函數可用于線程間的同步。

int pthread_mutex_init(
?????????????????? pthread_mutex_t *mutex,
?????????????????? const pthread_mutex_attr_t* attr
?????????????????? );
//該函數初始化一個互斥體變量,如果參數attr 為NULL,則互斥
//體變量mutex 使用默認的屬性。

int pthread_mutex_lock(
?????????????????? pthread_mutex_t *mutex
?????????????????? );
// 該函數用來鎖住互斥體變量。如果參數mutex 所指的互斥體已經
//被鎖住了,那么發出調用的線程將被阻塞直到其他線程對mutex 解鎖。

int pthread_mutex_trylock(
????????????????????? pthread_t *mutex
????????????????????? );
//該函數用來鎖住mutex 所指定的互斥體,但不阻塞。如果該互斥
//體已經被上鎖,該調用不會阻塞等待,而會返回一個錯誤代碼。

int pthread_mutex_unlock(
???????????????????? pthread_mutex_t *mutex
???????????????????? );
//該函數用來對一個互斥體解鎖。如果當前線程擁有參數mutex 所
//指定的互斥體,該調用將該互斥體解鎖。

int pthread_mutex_destroy (
?????????????????????? pthread_mutex_t *mutex
?????????????????????? );
//該函數用來釋放分配給參數mutex 的資源。調用成功時返回值為
//0, 否則返回一個非0 的錯誤代碼。

int pthread_cond_init(
????????????????? pthread_cond_t *cond,
????????????????? const pthread_cond_attr_t*attr
????????????????? );
//該函數按參數attr指定的屬性創建一個條件變量。調用成功返回,
//并將條件變量ID 賦值給參數cond,否則返回錯誤代碼。

int pthread_cond_wait (
?????????????????? pthread_cond_t *cond ,
?????????????????? pthread_mutex_t*mutex
?????????????????? );
// 該函數調用為參數mutex 指定的互斥體解鎖,等待一個事件(由
//參數cond 指定的條件變量)發生。調用該函數的線程被阻塞直到有其他
//線程調用pthread_cond_signal 或pthread_cond_broadcast 函數置相應的條
//件變量,而且獲得mutex 互斥體時才解除阻塞。

int pthread_cond_timewait(
????????????????????? pthread_cond_t *cond ,
????????????????????? pthread_mutex_t*mutex ,
????????????????????? const struct timespec *abstime
????????????????????? );
// 該函數與pthread_cond_wait 不同的是當系統時間到達abstime 參數指定的時間時,被阻塞線程也可以被喚起繼續執行。

int pthread_cond_broadcast(
?????????????????????? pthread_cond_t *cond
?????????????????????? );
// 該函數用來對所有等待參數cond所指定的條件變量的線程解除阻塞,調用成功返回0,否則返回錯誤代碼。

int pthread_cond_signal(
??????????????????? pthread_cond_t *cond
??????????????????? );
// 該函數的作用是解除一個等待參數cond所指定的條件變量的線程的阻塞狀態。當有多個線程掛起等待該條件變量,也只喚醒一個線程。

int pthread_cond_destroy(
???????????????????? pthread_cond_t *cond
???????????????????? );
// 該函數的作用是釋放一個條件變量。釋放為條件變量cond 所分配的資源。調用成功返回值為0,否則返回錯誤代碼。
int pthread_key_create(
?????????????????? pthread_key_t key ,
?????????????????? void(*destructor(void*))
?????????????????? );
// 該函數創建一個鍵值,該鍵值映射到一個專有數據結構體上。如果第二個參數不是NULL,這個鍵值被刪除時將調用這個函數指針來釋放數據空間。
int pthread_key_delete(
?????????????????? pthread_key_t *key
?????????????????? );
// 該函數用于刪除一個由pthread_key_create 函數調用創建的TSD鍵。調用成功返回值為0,否則返回錯誤代碼。

int pthread_setspecific(
??????????????????? pthread_key_t key ,
??????????????????? const void(value)
??????????????????? );
// 該函數設置一個線程專有數據的值,賦給由pthread_key_create 創建的TSD 鍵,調用成功返回值為0,否則返回錯誤代碼。

void *pthread_getspecific(
??????????????????? pthread_key_t *key
??????????????????? );
// 該函數獲得綁定到指定TSD 鍵上的值。調用成功,返回給定參數key 所對應的數據。如果沒有數據連接到該TSD 鍵,則返回NULL。
int pthread_once(
???????????? pthread_once_t* once_control,
???????????? void(*init_routine)(void)
???????????? );
//該函數的作用是確保init_routine 指向的函數,在調用pthread_once的線程中只被運行一次。once_control 指向一個靜態或全局的變量。
? ======================================================================================== ? 1. 下載pthreads win32源代碼:
????ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.tar.gz
2. 編譯靜態庫:
make clean GC-static
在根目錄下面生成libpthreadGC2.a
3. 將生成的libpthreadGC2.a拷貝到mingw庫目錄下,將pthread.h, sched.h, semaphore.h拷貝到INCLUDE目錄下 4. 使用libpthread庫, 在程序起始處對libpthread作初始化:
#if defined(PTW32_STATIC_LIB)
??? ptw32_processInitialize();
#endif
5. 編譯時確保傳入-DPTW32_STATIC_LIB,鏈接時加入-lpthreadGC2, OK!

總結

以上是生活随笔為你收集整理的跨平台多线程编程的全部內容,希望文章能夠幫你解決所遇到的問題。

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