1 /*
2 * 2. Create 4 calling threads, and then the main thread is responsible for filling a data into the global variable box each time. After the data is filled in, one of the 4 threads will take out the data
3 * and analyze whether it contains the number '0' ' After the last main thread allocation is completed, cancel the thread fetching data through the cancellation mechanism
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.\n " );
32 return 1 ;
33 }
34 }
35 // Assign tasks (fill data)
36 for (num= 1 ;num<= 1000 ;num++ )
37 {
38 pthread_mutex_lock(& mm);
39 while (box!= 0 )
40 {
41 pthread_cond_wait(&empty,& mm); // Wait for the empty signal, sleep and release the lock if not, wake up holding the lock, wait if there is no lock
42 }
43 box= num;
44 pthread_mutex_unlock(& mm); // release the lock
45 pthread_cond_signal (& fully); // signal
46 }
47
48
49 pthread_mutex_lock(& mm); //locking here is to ensure that the following cancellation request is executed after the last data is fetched,
preventing the secondary thread from getting the data Coming and processing is cancelled, causing data loss
50 while (box!= 0 )
51 {
52 pthread_cond_wait(&empty,& mm);
53 }
54 pthread_mutex_unlock(& mm);
55
56 //sleep(3);
57 // Task distribution completes cancel end task thread
58 for (i= 0 ;i<NR;i++ )
59 {
60 ret= pthread_cancel(tid[i ]);
61 if (ret!= 0 ){
62 fprintf(stderr, " Failed to send cancel request <%dth> thread!\n " ,i);
63 i--; // try again
64 }
65 }
66
67 // Block and wait for the end of the task thread
68 for (i= 0 ;i<NR;i++ )
69 {
70 pthread_join(tid[i],NULL);
71 }
72 printf( " ====work over=====\n " );
73
74 return 0 ;
75 }
76 void *doWork( void * arg)
77 {
78 int num;
79
80 // Set the thread to exit the cleanup program for the thread holding the lock to be cancelled but not unlocked
81 pthread_cleanup_push(safeExit,NULL);
82
83 while( 1 )
84 {
85 pthread_mutex_lock(& mm);
86 while (box== 0 )
87 {
88 /*
89 The cancel request comes to wake up the thread that is sleeping here, but this thread must hold the lock mm when it wakes up, and then respond to cancel,
90 If a thread is awakened by cancel and cannot acquire the lock mm, it will block again and wait for the lock to be cancelled
. 91 */
92 pthread_cond_wait(&fully,& mm);
93 }
94
95 // Ensure that the task is completely completed when it is canceled
96 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
97 num=box;// Remove the data
98 box= 0 ; // Empty the data box
99 pthread_mutex_unlock(& mm);
100 pthread_cond_signal(& empty);
101
102
103 // Process the data slowly
104 if (checkNum(num, 0 ))
105 {
106 printf( " %dth thread num:%d include '0'\n " ,( long )arg,num);
107 }
108 else
109 {
110 printf( "%dth thread num:%d not include '0'\n",(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 ); // It takes a certain amount of time to simulate the analysis data
126 } while (num!= 0 );
127
128 return 0 ;
129 }
130 void safeExit( void ) //Guaranteed that the lock is added and then subtracted, whoever adds and subtracts
131 {
132 // Test whether the lock is held
133 pthread_mutex_trylock(& mm);
134
135 pthread_mutex_unlock(&mm);
136 }