深夜本来都打算弄完睡觉,结果被一个莫名其妙的锁搞得莫名其妙,为了让同步问题明显地表现出来,主线程和子线程都加了一个sleep 1秒,使得都来不及减减操作,if判断就都为真,导致结果变成了-1,但这不是想要的结果
于是想通过互斥量加锁,让一个if以及减减线执行完,然后解锁再执行另一个,可居然还是返回-1,更奇怪的是,去掉两个线程里的sleep,锁就起效果了,难道是这中间的具体实现流程问题没完全弄清楚?
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> int i = 1; pthread_mutex_t mutex; void *thread_function(){ pthread_mutex_lock(&mutex); if (i > 0){ sleep(1); --i; } pthread_mutex_unlock(&mutex); pthread_exit("See you, lihui"); } int main(){ pthread_t child; if (pthread_create(&child, NULL, thread_function, NULL)){ printf("Create new thread failed!\n"); exit(1); } pthread_mutex_lock(&mutex); if (i > 0){ sleep(1); --i; } pthread_mutex_unlock(&mutex); pthread_join(child, NULL); printf("i = %d\n", i); return 0; }
执行,神奇的结果:
lihui@2015 ~ $ ./a.exe i = -1
这就很奇怪了,这锁应该加得没问题呀,只好gdb了一把,但是神奇的一幕出现了:
Reading symbols from ./a.exe...done. (gdb) b 12 Breakpoint 1 at 0x1004010f1: file he.c, line 12. (gdb) b 27 Breakpoint 2 at 0x100401184: file he.c, line 27. (gdb) r Starting program: /home/lihui/a.exe [New Thread 6772.0x1b9c] [New Thread 6772.0xf3c] [New Thread 6772.0x1da4] Breakpoint 2, main () at he.c:27 27 sleep(1); (gdb) c Continuing. [Switching to Thread 6772.0x1da4] Breakpoint 1, thread_function () at he.c:12 12 sleep(1); (gdb) c Continuing. [Thread 6772.0x1da4 exited with code 0] i = -1
主线程和子线程的if判断居然都为真,也就是这锁完全没起作用?这就奇怪了,这么简单的程序,感觉没明显错误呀,抱着试一试的态度,把两个sleep给去掉,不试不知道,一试吓一跳:
lihui@2015 ~ $ ./a.exe i = 0
但其实这样做是没道理的,因为没有了sleep,不加锁执行结果也会是0,就因为这样我猜加了两个sleep凸显一下问题,但事实上加了sleep的确结果就变了,已经开始怀疑在锁里加sleep会不会有不明确的问题,还搜索了半天,一无所获
准备收工睡觉的时候,不死心,心想会不会是cygwin的问题,直接copy sourcecode到服务器linux系统执行了一把,神了,加sleep结果也是0,顿时心中突然冒出来多少只那啥,上次一个程序也是,还好这次没浪费太多时间
[lihui@localhost ~]# gcc -g hello.c -lpthread [lihui@localhost ~]# ./a.out i = 0 ... Reading symbols from /root/a.out...done. (gdb) b 12 Breakpoint 1 at 0x4007ac: file hello.c, line 12. (gdb) b 27 Breakpoint 2 at 0x400828: file hello.c, line 27. (gdb) r Starting program: /root/a.out [Thread debugging using libthread_db enabled] [New Thread 0x7ffff7ff2700 (LWP 9063)] Breakpoint 2, main () at hello.c:27 27 sleep(1); Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.107.el6.x86_64 (gdb) c Continuing. i = 0 [Thread 0x7ffff7ff2700 (LWP 9063) exited] Program exited normally. Missing separate debuginfos, use: debuginfo-install libgcc-4.4.7-4.el6.x86_64 (gdb)
果然,只跳进去了一个sleep,锁生效了,难道cygwin和linux有关thread加锁也有这么大差异??