2、再看看用信号量来解决多线程的同步问题,程序代码如下: #include<stdio.h> #include<pthread.h> #include<errno.h> #include<stdlib.h> #include<unistd.h> #include <semaphore.h>
void* ticketport1(void*); void* ticketport2(void*);
int tickets=100; sem_t mutex,full; //定义两个信号量
int main() { int ret; pthread_t id1,id2;
ret=sem_init(&mutex,0,1); //初始化mutex信号量为1 ret+=sem_init(&full,0,0); //初始化full信号量为0 if(ret!=0) { perror("sem_init"); } ret=pthread_create(&id1,NULL,ticketport1,NULL); if(ret<0) { perror("creat thread1:"); exit(-1); } ret=pthread_create(&id2,NULL,ticketport2,NULL); if(ret<0) { perror("creat thread2:"); exit(-1); }
pthread_join(id1,NULL); pthread_join(id2,NULL); return 0; }
void* ticketport1(void* arg) { while(1) { sem_wait(&mutex); //mutex信号量进行P操作 if(tickets>0) { usleep(1000); printf("thread1 sell ticket: %d\n",tickets--); sem_post(&full); //full信号量进行V操作 } else { sem_post(&full); //full信号量进行V操作 break; }
} return (void*)0; }
void* ticketport2(void* arg) { while(1) { sem_wait(&full); //full信号量进行P操作 if(tickets>0) { usleep(1000); printf("thread2 sell ticket: %d\n",tickets--); sem_post(&mutex); //mutex信号量进行V操作 } else { sem_post(&mutex); //mutex信号量进行V操作 break; }
} return (void*)0; } 上面的sem_init函数用来初始化两个信号量的初始化值,这里一个设为1,一个设为0,sem_wait类似于P操作,让信号量减1,如果小于结果小于0,线程阻塞,否则线程继续执行,sem_post类似于V操作,提升信号量的值,加1,通过这两个信号量之间的互相“救对方”,就可以实现这两个线程的同步执行。 我们编译运行以上程序,发现两个售票点交替卖票,两个纯程依次得到机会执行,并且不会有0号票卖出,实现了同步。
3、我们再用条件变量来解决同步问题,一般条件变量需要结合互斥量一起使用,代码如下: #include<stdio.h> #include<pthread.h> #include<errno.h> #include<stdlib.h> #include<unistd.h> void* ticketport1(void*); void* ticketport2(void*); int tickets=100; pthread_mutex_t mutex; pthread_cond_t qready=PTHREAD_COND_INITIALIZER; //静态初始化条件变量; int main() { int ret; pthread_t id1,id2; pthread_mutex_init(&mutex,NULL); //初始化互斥量 ret=pthread_create(&id1,NULL,ticketport1,NULL); if(ret<0) { perror("creat thread1:"); exit(-1); } ret=pthread_create(&id2,NULL,ticketport2,NULL); if(ret<0) { perror("creat thread2:"); exit(-1); } pthread_join(id1,NULL); pthread_join(id2,NULL); }
void* ticketport1(void* arg) { pthread_mutex_lock(&mutex); //给互斥量上锁 while(tickets > 0) { if(tickets%2 == 1) { usleep(1000); printf("thread1 sell ticket: %d\n",tickets--); pthread_cond_signal(&qready); //条件改变,发送信号,通知ticketport2 } else { pthread_cond_wait(&qready,&mutex); //解开mutex,并等待qready改变 } pthread_mutex_unlock(&mutex); //给互斥量解锁 } return (void*)0; }
void* ticketport2(void* arg) { pthread_mutex_lock(&mutex); //给互斥量上锁 while(tickets > 0) { if(tickets%2==0) { usleep(1000); printf("thread2 sell ticket: %d\n",tickets--); pthread_cond_signal(&qready); //条件改变,发送信号,通知ticketport1 } else { pthread_cond_wait(&qready,&mutex); //解开mutex,并等待qready改变 } pthread_mutex_unlock(&mutex); //给互斥量解锁 } return (void*)0; } 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件变量发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线程间的同步. 函数pthread_cond_wait使线程阻塞在一个条件变量上,而函数pthread_cond_signal是用来释放被阻塞在条件变量上的一个线程。但是要注意的是,条件变量只是起到阻塞和唤醒线程的作用,具体的判断条件还需用户给出,我这里给出的是tickets是否是偶数这个条件。 |