標籤:lock 大小 har 工作 white and use android l github
本文起初主要想寫個示範範例實測下pthread_mutex_lock和pthread_mutex_trylock差別。在linux機器上非常快就over了,可是想了一下。pthread是unix系的,在windows沒辦法直接執行代碼非常不方便。於是想到了android,windows上安裝ndk,手機root就能夠跑pthread代碼咯。。。
demolock和trylock的差別也非常好理解:,前者是堵塞的。死等知道相互排斥鎖被釋放;而後者則更加靈活。
淺嘗輒止。做個嘗試不行則幹其它事情去。。測試代碼pt_lock.c例如以下:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#include <unistd.h>#include <sys/types.h>typedef pthread_t pt_t;typedef unsigned int uint_t;pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER;void lock_func(void* arg){pid_t pid;//processpt_t tid;// threadpid = getpid();tid = pthread_self();printf("want to lock mutex, msg=%s, tid=%u\n", (char*)arg, (uint_t)tid);pthread_mutex_lock( &mt );printf("I[tid=%u] am using, (*|^_^|*)\n", (uint_t)tid);sleep(10);pthread_mutex_unlock( &mt );}void try_lock_func(void* arg){uint_t tid = (uint_t)pthread_self();int counter = 0;while ( pthread_mutex_trylock( &mt ) ){sleep(1);++counter;printf("after sleep 1s, i [tid=%u] want to try again, iter=%d.\n", tid, counter);}printf("It is my[tid=%u] turn, so long i waited...msg=%s\n", tid, (char*)arg);pthread_mutex_unlock( &mt );}#define XX_CREATE_FAILED(err)printf("create thread error : %s\n", strerror(err));return 1;int main(){int rc;pt_t pt1, pt2, pt3;const char* msg1 = "block";const char* msg2 = "unblock";rc = pthread_create(&pt1, NULL, (void*)&lock_func, (void*)msg1);if (rc != 0) {XX_CREATE_FAILED(rc);}rc = pthread_create(&pt2, NULL, (void*)&lock_func, (void*)msg1);if (rc != 0){XX_CREATE_FAILED(rc);}sleep(1);rc = pthread_create(&pt3, NULL, (void*)&try_lock_func, (void*)msg2);if (rc != 0){XX_CREATE_FAILED(rc);}pthread_join(pt1, NULL);pthread_join(pt2, NULL);pthread_join(pt3, NULL);return 0;}代碼思路也非常好理解:建立三個線程。1和2通過lock方式去爭搶mt相互排斥鎖,3線程則靈活,每隔1秒去檢測下mt相互排斥鎖能否夠用,不會堵塞。
線程1或者2佔有mt的時間為10秒。
linux run
[email protected]:~/peteryfren/cpp/pthread> gcc -Wall -o pt_lock pt_lock.c -lpthread[email protected]:~/peteryfren/cpp/pthread> ./pt_lock
輸出結果與預期一致,id=1082132800線程先佔有mt。10s內線程tid=1090525504堵塞,而線程tid=1098918208每隔1s測試下mt可用性。
want to lock mutex, msg=block, tid=1082132800I[tid=1082132800] am using, (*|^_^|*)want to lock mutex, msg=block, tid=1090525504after sleep 1s, i [tid=1098918208] want to try again, iter=1.after sleep 1s, i [tid=1098918208] want to try again, iter=2.after sleep 1s, i [tid=1098918208] want to try again, iter=3.after sleep 1s, i [tid=1098918208] want to try again, iter=4.after sleep 1s, i [tid=1098918208] want to try again, iter=5.after sleep 1s, i [tid=1098918208] want to try again, iter=6.after sleep 1s, i [tid=1098918208] want to try again, iter=7.after sleep 1s, i [tid=1098918208] want to try again, iter=8.I[tid=1090525504] am using, (*|^_^|*)after sleep 1s, i [tid=1098918208] want to try again, iter=9.after sleep 1s, i [tid=1098918208] want to try again, iter=10.after sleep 1s, i [tid=1098918208] want to try again, iter=11.after sleep 1s, i [tid=1098918208] want to try again, iter=12.after sleep 1s, i [tid=1098918208] want to try again, iter=13.after sleep 1s, i [tid=1098918208] want to try again, iter=14.after sleep 1s, i [tid=1098918208] want to try again, iter=15.after sleep 1s, i [tid=1098918208] want to try again, iter=16.after sleep 1s, i [tid=1098918208] want to try again, iter=17.after sleep 1s, i [tid=1098918208] want to try again, iter=18.after sleep 1s, i [tid=1098918208] want to try again, iter=19.It is my[tid=1098918208] turn, so long i waited...msg=unblock
android runandroid上編譯和執行pt_lock參考前一篇blog:http://blog.csdn.net/ryfdizuo/article/details/28891649 詳細批處理run.cmd例如以下:
@echo "1. build .o file"@Rem fPIE flag is used in compiling stage.D:\android-ndk-r9b-windows-x86\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\arm-linux-androideabi-gcc.exe --sysroot=D:\android-ndk-r9b-windows-x86\platforms\android-13\arch-arm -fPIE -c pt_lock.c@echo "2. build exec file"@Rem pie flag is used in linking stage.D:\android-ndk-r9b-windows-x86\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\arm-linux-androideabi-gcc.exe --sysroot=D:\android-ndk-r9b-windows-x86\platforms\android-13\arch-arm -pie -o pt_lock pt_lock.o@pause
裡面的gcc和android系統庫路徑須要依據機器上實際位置改動。
注意android上gcc編譯與linux上有點點區別:ndk中gcc不須要須要顯式指定-lpthread。可能pthread預設就會連結。
android-ndk-r9b-windows-x86\platforms\android-13\arch-arm\usr\lib檔案夾下的這些so載入須要指定。。在Android.mk中類似。命令列下執行run.cmd,編譯pt_lock,然後推到手機上,注意我的nexus4必須是/data/local/tmp以下才有許可權,執行後有錯誤,詳細步驟:
E:\GitHub\ndk_tutorial\pthread_playground>adb shell[email protected]:/ # cd /data/local/tmpcd /data/local/tmp[email protected]:/data/local/tmp # mv /sdcard/pt_lock ./mv /sdcard/pt_lock ./[email protected]:/data/local/tmp # chmod 751 pt_lockchmod 751 pt_lock[email protected]:/data/local/tmp # ./pt_lockerror: only position independent executables (PIE) are supported.
報了PIE不支援的錯誤,n4上安裝的是android L系統。gg後知道編譯的連結的須要添加pie等設定,參見[ref2],fPIE是編譯時間候的選項,pie是連結時候的選項。再次又一次編譯,推到手機上執行OK。。。pt_lock.c不須要做不論什麼改動。
pthread學習
1.線程相關1)回呼函數類型 void* (*pfunc) (void* arg) 。參數通過void*傳入,多個參數是通過結構體/數組打包。2)線程屬性,能夠設定線程類型,通常是joinable。設定線程棧的大小。假設線程內部要定義大數組一定小心棧越界。
3)線程終止的幾種情況:
- 回呼函數執行完畢。正常退出
- 線程內調用pthread_exit函數。無論是否完畢都退出。該函數後面的全部代碼都不會被執行(尤其printf等語句)。
- 其它線程顯式調用pthread_cancel 結束當前線程。
- 整個進程被終止,由於調用了exit等函數。它以下的全部線程都被殺死。資源被回收。
- main函數建立N個線程。兩種做法等待其它線程結束:顯式pthread_join等待其它線程結束;main函數中調用pthread_exit,等待其它線程結束。
2. 相互排斥鎖相關
pthread_mutex_initpthread_mutex_lock。堵塞等待
pthread_mutex_trylock,非堵塞等待
pthread_mutex_destroy
3. 訊號量相關pthread_mutex_initpthread_mutex_wait 堵塞當前線程,直到滿足某些條件時。虛擬碼例如以下:beginpthread_mutex_unlock( mutex ) 堵塞之前釋放相互排斥鎖block_on_cond( condition ) 條件堵塞pthread_mutex_lock(mutex) 條件滿足後 佔有相互排斥鎖,完畢工作後須要釋放相互排斥鎖end該語句必須在迴圈中運行,而不是if中,由於線程之間可能有虛假的喚醒行為,spurious wakeup。當喚醒時須要再次確定預期的條件是否滿足。假設不滿足繼續等待。
相關的討論參見:http://a-shi.org/blog/2012/07/27/pthread_cond_wait_mutex_while/
pthread_mutex_signal,僅僅有一個線程等待時發送訊號量
pthread_mutex_broadcast 多個線程同一時候等待時使用
pthread_mutex_destroy
4. 生存者/消費者,讀寫。哲學家進餐模型http://www.cs.nmsu.edu/~jcook/Tools/pthreads/examples.htmlrefer
1. gcc以下的pie和fPIE 選項標誌解說,http://richardustc.github.io/blog/2013/05/pie/
2. android L系統下PIE錯誤,http://blog.csdn.net/hxdanya/article/details/39371759
3. pthread http://man7.org/linux/man-pages/man3/pthread_create.3.html
linux和android端的pthread學習