本文起初主要想写个示例实测下pthread_mutex_lock和pthread_mutex_trylock区别。在linux机器上很快就over了,但是想了一下,pthread是unix系的,在windows没办法直接运行代码很不方便。于是想到了android,windows上安装ndk,手机root就可以跑pthread代码咯。。。
#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; //process pt_t tid; // thread pid = 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秒。
xx@h10-1-152-72:~/peteryfren/cpp/pthread> gcc -Wall -o pt_lock pt_lock.c -lpthread xx@h10-1-152-72:~/peteryfren/cpp/pthread> ./pt_lock输出结果与预期一致,id=1082132800线程先占有mt,10s内线程tid=1090525504阻塞,而线程tid=1098918208每隔1s测试下mt可用性。
want to lock mutex, msg=block, tid=1082132800 I[tid=1082132800] am using, (*|^_^|*) want to lock mutex, msg=block, tid=1090525504 after 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
@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系统库路径需要根据机器上实际位置修改。
E:\GitHub\ndk_tutorial\pthread_playground>adb shell root@mako:/ # cd /data/local/tmp cd /data/local/tmp root@mako:/data/local/tmp # mv /sdcard/pt_lock ./ mv /sdcard/pt_lock ./ root@mako:/data/local/tmp # chmod 751 pt_lock chmod 751 pt_lock root@mako:/data/local/tmp # ./pt_lock error: only position independent executables (PIE) are supported.报了PIE不支持的错误,n4上安装的是android L系统,gg后知道编译的链接的需要增加pie等设置,参见[ref2],fPIE是编译时候的选项,pie是链接时候的选项,再次重新编译,推到手机上运行OK。。。pt_lock.c不需要做任何修改。
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