1. 演示一个例子,出现死锁,用strace debug得到
#include<stdio.h> #include<pthread.h> #include<stdlib.h> #include<string.h> #include<semaphore.h> sem_t sem; typedef struct _cal_ { int sum; }CAL; CAL cal; void *calculate(void*arg) { int i; int sum; for(i = 0; i < 100; i++) { cal.sum = cal.sum + i; } sem_post(&sem); } void *sum(void *arg) { sem_wait(&sem); printf("the sum is %d\n",cal.sum); } void *times(void *arg) { sem_wait(&sem); printf("the times is %d\n",cal.sum * cal.sum); } int main(void) { int ret=-1; pthread_t th[3]; sem_init(&sem,0,0); ret = pthread_create(&th[0],NULL,calculate,NULL); if (ret != 0) { printf("Pthread_create failed\n"); return -1; } ret = pthread_create(&th[1],NULL,sum,NULL); if (ret != 0) { printf("Pthread_create failed\n"); return -1; } ret = pthread_create(&th[1],NULL,times,NULL); if (ret != 0) { printf("Pthread_create failed\n"); return -1; } pthread_join(th[0],NULL); pthread_join(th[1],NULL); pthread_join(th[2],NULL); return 0; }
mprotect(0xb5d46000, 4096, PROT_NONE) = 0 clone(child_stack=0xb6546464, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb6546ba8, {entry_number:6, base_addr:0xb6546b40, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xb6546ba8) = 17181 futex(0xb6546ba8, FUTEX_WAIT, 17181, NULL
futex(0xb7533ba8, FUTEX_WAIT, 17204, NULLthe times is 4950 ) = 0 --- SIGSEGV (Segmentation fault) @ 0 (0) --- +++ killed by SIGSEGV (core dumped) +++ Segmentation fault (core dumped)
上述的log表明,该code出现死锁,FUTEX_WAIT....... 而且Core Dumped 虽然times is 9801结果出来。(一开始测试不出来)
2. 基于信号量的问题,需要进行优化和解决:
更新一版代码:
#include<stdio.h> #include<pthread.h> #include<stdlib.h> #include<string.h> #include<semaphore.h> sem_t sem_cal; sem_t sem_times; typedef struct _cal_ { int sum; }CAL; CAL cal; void *calculate(void*arg) { int i; int sum; for(i = 0; i < 100; i++) { cal.sum = cal.sum + i; } sem_post(&sem_cal); } void *sum(void *arg) { sem_wait(&sem_cal); printf("the sum is %d\n",cal.sum); sem_post(&sem_times); } void *times(void *arg) { sem_wait(&sem_times); printf("the times is %d\n",cal.sum * cal.sum); } int main(void) { int ret=-1; pthread_t th[3]; sem_init(&sem_cal,0,0); sem_init(&sem_times,0,0); ret = pthread_create(&th[0],NULL,calculate,NULL); if (ret != 0) { printf("Pthread_create failed\n"); return -1; } ret = pthread_create(&th[1],NULL,sum,NULL); if (ret != 0) { printf("Pthread_create failed\n"); return -1; } ret = pthread_create(&th[1],NULL,times,NULL); if (ret != 0) { printf("Pthread_create failed\n"); return -1; } pthread_join(th[0],NULL); pthread_join(th[1],NULL); pthread_join(th[2],NULL); return 0; }
但是出现:
the sum is 4950 the times is 24502500 Segmentation fault (core dumped)
futex(0xb65afba8, FUTEX_WAIT, 17277, NULL) = -1 EAGAIN (Resource temporarily unavailable)
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
此时出现段错误,但是结果都正常。
Resource temporarily unavailable 表明资源冲突
3. 跟着解决这个段错误的问题:
原来是 ret = pthread_create(&th[1],NULL,times,NULL);同一个线程ID。
(DUANG)
#include<stdio.h> #include<pthread.h> #include<stdlib.h> #include<string.h> #include<semaphore.h> sem_t sem_cal; sem_t sem_times; typedef struct _cal_ { int sum; }CAL; CAL cal; void *calculate(void*arg) { int i; int sum; for(i = 0; i < 100; i++) { cal.sum = cal.sum + i; } sem_post(&sem_cal); } void *sum(void *arg) { sem_wait(&sem_cal); printf("the sum is %d\n",cal.sum); sem_post(&sem_times); } void *times(void *arg) { sem_wait(&sem_times); printf("the times is %d\n",cal.sum * cal.sum); } int main(void) { int ret=-1; pthread_t th[3]; sem_init(&sem_cal,0,0); sem_init(&sem_times,0,0); ret = pthread_create(&th[0],NULL,calculate,NULL); if (ret != 0) { printf("Pthread_create failed\n"); return -1; } ret = pthread_create(&th[1],NULL,sum,NULL); if (ret != 0) { printf("Pthread_create failed\n"); return -1; } ret = pthread_create(&th[2],NULL,times,NULL); if (ret != 0) { printf("Pthread_create failed\n"); return -1; } pthread_join(th[0],NULL); pthread_join(th[1],NULL); pthread_join(th[2],NULL); return 0; }
该博客的目的是:
1. 通过多个信号量去完成业务。
2. 信号量和互斥锁的区别下节分析。
Life is mess, don't let mess mess us.