1 /*
2 * 2.创建4个调用线程,然后主线程每次负责向全局变量box填一个数据,数据填好后4个线程中某个线程将数据
3 * 取出并分析是否包含数字'0' 最后主线程分配完成后 通过取消机制取消取数据的线程
4 */
5
6 #include <stdio.h>
7 #include <pthread.h>
8
9 #define NR 4
10
11 static pthread_mutex_t mm =PTHREAD_MUTEX_INITIALIZER;
12 static pthread_cond_t empty=PTHREAD_COND_INITIALIZER;
13 static pthread_cond_t fully=PTHREAD_COND_INITIALIZER;
14
15 static int box=0;
16
17 void *doWork(void *arg);
18 int checkNum(int num,int n);
19 void safeExit(void);
20
21 int main(void)
22 {
23 long i,num,ret;
24 pthread_t tid[NR];
25
26 for(i=0;i<NR;i++)
27 {
28 ret=pthread_create(&tid[i],NULL,doWork,(void *)i);
29 if(ret!=0)
30 {
31 fprintf(stderr,"create thread failed.
");
32 return 1;
33 }
34 }
35 //分配任务(填装数据)
36 for(num=1;num<=1000;num++)
37 {
38 pthread_mutex_lock(&mm);
39 while(box!=0)
40 {
41 pthread_cond_wait(&empty,&mm); //等待empty信号,没有则睡眠并释放锁,唤醒持有锁,没锁则等待
42 }
43 box=num;
44 pthread_mutex_unlock(&mm); //释放锁
45 pthread_cond_signal(&fully); //发信号
46 }
47
48
49 pthread_mutex_lock(&mm); //此处加锁是保证最后一个数据取完以后再开始执行下面的取消请求,
防止次线程拿到数据还没来的及处理就被取消,造成数据丢失
50 while(box!=0)
51 {
52 pthread_cond_wait(&empty,&mm);
53 }
54 pthread_mutex_unlock(&mm);
55
56 //sleep(3);
57 //任务分发完成 取消结束任务线程
58 for(i=0;i<NR;i++)
59 {
60 ret=pthread_cancel(tid[i]);
61 if(ret!=0){
62 fprintf(stderr,"发送取消请求<%dth>线程失败!
",i);
63 i--;//再次重试
64 }
65 }
66
67 //阻塞等待任务线程结束
68 for(i=0;i<NR;i++)
69 {
70 pthread_join(tid[i],NULL);
71 }
72 printf("====work over=====
");
73
74 return 0;
75 }
76 void *doWork(void *arg)
77 {
78 int num;
79
80 //设定线程退出清理程序 用于线程持有锁被取消而未解锁
81 pthread_cleanup_push(safeExit,NULL);
82
83 while(1)
84 {
85 pthread_mutex_lock(&mm);
86 while(box==0)
87 {
88 /*
89 cancel请求到来 唤醒此处休眠的线程 但是此线程醒来必须持有锁mm,然后响应 cancel,
90 如果某个线程被cancel唤醒而又无法获取到锁mm 则再次阻塞等锁 此时无法取消
91 */
92 pthread_cond_wait(&fully,&mm);
93 }
94
95 //确保被取消时任务完整完成
96 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
97 num=box;//取走数据
98 box=0;//清空数据盒子
99 pthread_mutex_unlock(&mm);
100 pthread_cond_signal(&empty);
101
102
103 //再慢慢去处理数据
104 if(checkNum(num,0))
105 {
106 printf("%dth thread num:%d include '0'
",(long)arg,num);
107 }
108 else
109 {
110 printf("%dth thread num:%d not include '0'
",(long)arg,num);
111 }
112 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
113 pthread_testcancel();//设置取消点
114 }
115
116 return (void *)0;
117 pthread_cleanup_pop(0);
118 }
119 int checkNum(int num,int n)
120 {
121 do{
122 if(num%10==n)
123 return 1;
124 num/=10;
125 usleep(20000);//模拟分析数据需要一定的时间
126 }while(num!=0);
127
128 return 0;
129 }
130 void safeExit(void) //保证 锁有加才有减,谁加谁减
131 {
132 //测试是否持有锁
133 pthread_mutex_trylock(&mm);
134
135 pthread_mutex_unlock(&mm);
136 }