单页面销售信网站赚钱系统,网站微信开发,深圳调查公司,常德最新确诊人员名单一、 为什么要用多线程技术#xff1f; 1、避免阻塞#xff0c;大家知道#xff0c;单个进程只有一个主线程#xff0c;当主线程阻塞的时候#xff0c;整个进程也就阻塞了#xff0c;无法再去做其它的一些功能了。 2、避免CPU空转#xff0c;应用程序经常会涉及到RPC 1、避免阻塞大家知道单个进程只有一个主线程当主线程阻塞的时候整个进程也就阻塞了无法再去做其它的一些功能了。 2、避免CPU空转应用程序经常会涉及到RPC数据库访问磁盘IO等操作这些操作的速度比CPU慢很多而在等待这些响应时CPU却不能去处理新的请求导致这种单线程的应用程序性能很差。 3、提升效率一个进程要独立拥有4GB的虚拟地址空间而多个线程可以共享同一地址空间线程的切换比进程的切换要快得多。 二、 如何使用多线程技术进行编程 下面给出个多线程程序一个最简单的模拟售票系统代码如下 [cpp] view plaincopy #include stdio.h #include pthread.h void *ticketsell1(void *); void *ticketsell2(void *); int tickets 20; int main() { pthread_t id1,id2; int error; error pthread_create(id1, NULL, ticketsell1, NULL); if(error ! 0) { printf(pthread is not created!\n); return -1; } error pthread_create(id2, NULL, ticketsell2, NULL); if(error ! 0) { printf(pthread is not created!\n); return -1; } pthread_join(id1,NULL); pthread_join(id2,NULL); return 0; } void *ticketsell1(void *arg) { while(1) { if(tickets 0) { // usleep(1000); printf(ticketse1 sells ticket:%d\n,tickets--); } else { break; } } return (void *)0; } void *ticketsell2(void *arg) { while(1) { if(tickets 0) { // usleep(1000); printf(ticketse2 sells ticket:%d\n,tickets--); } else { break; } } return (void *)0; } 执行结果如下 [cpp] view plaincopy fsubuntu:~/qiang/mthread$ ./mthread1 ticketse2 sells ticket:20 ticketse2 sells ticket:19 ticketse2 sells ticket:18 ticketse2 sells ticket:17 ticketse2 sells ticket:16 ticketse2 sells ticket:15 ticketse2 sells ticket:14 ticketse2 sells ticket:13 ticketse2 sells ticket:12 ticketse2 sells ticket:11 ticketse2 sells ticket:10 ticketse2 sells ticket:9 ticketse2 sells ticket:8 ticketse2 sells ticket:7 ticketse2 sells ticket:6 ticketse2 sells ticket:4 ticketse2 sells ticket:3 ticketse2 sells ticket:2 ticketse2 sells ticket:1 ticketse1 sells ticket:5 看到结果我们发现时能正常卖票的一部分连续是sel2,另一部分是ticketsel1; 此时其实存在一个隐含的问题就是线程间的切换在单CPU系统中CPU是有时间片时间时间片到了就要执行其它的线程假设thread1执行到if里面但在printf执行前发生了线程切换那么会发生什么呢我们在这里用usleep函数(放开程序中的usleep注释行)进行强制模拟切换; 我们看看结果 [cpp] view plaincopy fsubuntu:~/qiang/mthread$ gcc -o mthread1 mthread1.c -lpthread fsubuntu:~/qiang/mthread$ ./mthread1 ticketse2 sells ticket:20 ticketse1 sells ticket:19 ticketse2 sells ticket:18 ticketse1 sells ticket:17 ticketse2 sells ticket:16 ticketse1 sells ticket:15 ticketse2 sells ticket:14 ticketse1 sells ticket:13 ticketse2 sells ticket:12 ticketse1 sells ticket:11 ticketse2 sells ticket:10 ticketse1 sells ticket:9 ticketse2 sells ticket:8 ticketse1 sells ticket:7 ticketse2 sells ticket:6 ticketse1 sells ticket:5 ticketse2 sells ticket:4 ticketse1 sells ticket:3 ticketse1 sells ticket:2 ticketse2 sells ticket:1 ticketse1 sells ticket:0 fsubuntu:~/qiang/mthread$ 运行程序发现竟然有0号票被卖出了这显然是错误的当thread1的if里面发生线程切换时thread2得到运行把最后一张票卖了此时thread1恢复运行结果卖出了0号票这里我们需要的是火车票的票数数据对于所有线程而言是同步的所以就要用到线程同步技术了。 三、 使用多线程的同步与互斥 1、多线程的同步方式有很多种例如互斥锁条件变量信号量读写锁。先看看互斥锁如何解决多线程之间的同步问题。程序用互斥锁后如下 [cpp] view plaincopy #include stdio.h #include pthread.h void *ticketsell1(void *); void *ticketsell2(void *); int tickets 20; pthread_mutex_t mutex; int main() { pthread_t id1,id2; pthread_mutex_init(mutex, NULL);// int error; error pthread_create(id1, NULL, ticketsell1, NULL); if(error ! 0) { printf(pthread is not created!\n); return -1; } error pthread_create(id2, NULL, ticketsell2, NULL); if(error ! 0) { printf(pthread is not created!\n); return -1; } pthread_join(id1,NULL); pthread_join(id2,NULL); return 0; } void *ticketsell1(void *arg) { while(1) { pthread_mutex_lock(mutex);//给互斥量上锁 if(tickets 0) { usleep(1000); printf(ticketse1 sells ticket:%d\n,tickets--); pthread_mutex_unlock(mutex);//给互斥量解锁 } else { pthread_mutex_unlock(mutex);//给互斥量解锁 break; } pthread_yield();//线程调度函数使每个线程都有执行机会 } return (void *)0; } void *ticketsell2(void *arg) { while(1) { pthread_mutex_lock(mutex);//给互斥量上锁 if(tickets 0) { usleep(1000); printf(ticketse2 sells ticket:%d\n,tickets--); pthread_mutex_unlock(mutex);//给互斥量解锁 } else { pthread_mutex_unlock(mutex);//给互斥量解锁 break; } pthread_yield();//线程调度函数是两个线程都有执行机会 } return (void *)0; } 执行结果如下 [cpp] view plaincopy fsubuntu:~/qiang/mthread$ vi mthread1.c fsubuntu:~/qiang/mthread$ gcc -o mthread1 mthread1.c -lpthread fsubuntu:~/qiang/mthread$ ./mthread1 ticketse2 sells ticket:20 ticketse1 sells ticket:19 ticketse2 sells ticket:18 ticketse1 sells ticket:17 ticketse2 sells ticket:16 ticketse1 sells ticket:15 ticketse2 sells ticket:14 ticketse1 sells ticket:13 ticketse2 sells ticket:12 ticketse1 sells ticket:11 ticketse2 sells ticket:10 ticketse1 sells ticket:9 ticketse2 sells ticket:8 ticketse1 sells ticket:7 ticketse2 sells ticket:6 ticketse1 sells ticket:5 ticketse2 sells ticket:4 ticketse1 sells ticket:3 ticketse2 sells ticket:2 ticketse1 sells ticket:1 2、再看看用信号量来解决多线程的同步问题程序代码如下 [cpp] view plaincopy #include stdio.h #include pthread.h #include semaphore.h void *ticketsell1(void *); void *ticketsell2(void *); int tickets 20; sem_t mutex,full; int main() { pthread_t id1,id2; int error; int ret; ret sem_init(mutex, 0 ,1);//初始化mutex信号量为1 ret sem_init(full, 0 ,0);//初始化full信号量为0 if(ret ! 0) { printf(sem_init fails!\n); } error pthread_create(id1, NULL, ticketsell1, NULL); if(error ! 0) { printf(pthread is not created!\n); return -1; } error pthread_create(id2, NULL, ticketsell2, NULL); if(error ! 0) { printf(pthread is not created!\n); return -1; } pthread_join(id1,NULL); pthread_join(id2,NULL); return 0; } void *ticketsell1(void *arg) { while(1) { sem_wait(mutex);//mutex信号量进行P操作 if(tickets 0) { usleep(1000); printf(ticketse1 sells ticket:%d\n,tickets--); sem_post(full);//full信号量进行V操作 } else { sem_post(full);//full信号量进行V操作 break; } } return (void *)0; } void *ticketsell2(void *arg) { while(1) { sem_wait(full);//full信号量进行P操作 if(tickets 0) { usleep(1000); printf(ticketse2 sells ticket:%d\n,tickets--); sem_post(mutex);//mutex信号量进行V操作 } else { sem_post(mutex);//mutex信号量进行V操作 break; } } return (void *)0; } 执行结果 [cpp] view plaincopy fsubuntu:~/qiang/mthread$ vi mthread1.c fsubuntu:~/qiang/mthread$ gcc -o mthread1 mthread1.c -lpthread fsubuntu:~/qiang/mthread$ ./mthread1 ticketse1 sells ticket:20 ticketse2 sells ticket:19 ticketse1 sells ticket:18 ticketse2 sells ticket:17 ticketse1 sells ticket:16 ticketse2 sells ticket:15 ticketse1 sells ticket:14 ticketse2 sells ticket:13 ticketse1 sells ticket:12 ticketse2 sells ticket:11 ticketse1 sells ticket:10 ticketse2 sells ticket:9 ticketse1 sells ticket:8 ticketse2 sells ticket:7 ticketse1 sells ticket:6 ticketse2 sells ticket:5 ticketse1 sells ticket:4 ticketse2 sells ticket:3 ticketse1 sells ticket:2 ticketse2 sells ticket:1 fsubuntu:~/qiang/mthread$ 上面的sem_init函数用来初始化两个信号量的初始化值这里一个设为1一个设为0sem_wait类似于P操作让信号量减1如果小于结果小于0线程阻塞否则线程继续执行sem_post类似于V操作提升信号量的值加1通过这两个信号量之间的互相“救对方”就可以实现这两个线程的同步执行。 我们编译运行以上程序发现两个售票点交替卖票两个纯程依次得到机会执行并且不会有0号票卖出实现了同步。 3、我们再用条件变量来解决同步问题一般条件变量需要结合互斥量一起使用代码如下 [cpp] view plaincopy #include stdio.h #include pthread.h #include semaphore.h void *ticketsell1(void *); void *ticketsell2(void *); int tickets 20; pthread_mutex_t mutex; pthread_cond_t qready PTHREAD_COND_INITIALIZER;//静态初始化条件变量; int main() { pthread_t id1,id2; pthread_mutex_init(mutex, NULL); int error; error pthread_create(id1, NULL, ticketsell1, NULL); if(error ! 0) { printf(pthread is not created!\n); return -1; } error pthread_create(id2, NULL, ticketsell2, NULL); if(error ! 0) { printf(pthread is not created!\n); return -1; } pthread_join(id1,NULL); pthread_join(id2,NULL); return 0; } void *ticketsell1(void *arg) { pthread_mutex_lock(mutex); while(tickets 0) { if(tickets%2 1) { usleep(1000); printf(ticketse1 sells ticket:%d\n,tickets--); pthread_cond_signal(qready);//条件改变发送信号通知ticketse2 } else { pthread_cond_wait(qready,mutex);//解开Mutex,并等待qready改变 } pthread_mutex_unlock(mutex);//给互斥量解锁 } return (void *)0; } void *ticketsell2(void *arg) { pthread_mutex_lock(mutex); while(tickets 0) { if(tickets%2 0) { usleep(1000); printf(ticketse2 sells ticket:%d\n,tickets--); pthread_cond_signal(qready);//条件改变发送信号通知ticketse1 } else { pthread_cond_wait(qready,mutex);//解开mutex,并等待qready改变 } pthread_mutex_unlock(mutex);//给互斥量解锁 } return (void *)0; } 执行结果如下 [cpp] view plaincopy fsubuntu:~/qiang/mthread$ vi mthread1.c fsubuntu:~/qiang/mthread$ gcc -o mthread1 mthread1.c -lpthread fsubuntu:~/qiang/mthread$ ./mthread1 ticketse2 sells ticket:20 ticketse1 sells ticket:19 ticketse2 sells ticket:18 ticketse1 sells ticket:17 ticketse2 sells ticket:16 ticketse1 sells ticket:15 ticketse2 sells ticket:14 ticketse1 sells ticket:13 ticketse2 sells ticket:12 ticketse1 sells ticket:11 ticketse2 sells ticket:10 ticketse1 sells ticket:9 ticketse2 sells ticket:8 ticketse1 sells ticket:7 ticketse2 sells ticket:6 ticketse1 sells ticket:5 ticketse2 sells ticket:4 ticketse1 sells ticket:3 ticketse2 sells ticket:2 ticketse1 sells ticket:1 fsubuntu:~/qiang/mthread$ 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足它常和互斥锁一起使用。使用时条件变量被用来阻塞一个线程当条件不满足时线程往往解开相应的互斥锁并等待条件变量发生变化。一旦其它的某个线程改变了条件变量它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来条件变量被用来进行线程间的同步. 函数pthread_cond_wait使线程阻塞在一个条件变量上,而函数pthread_cond_signal是用来释放被阻塞在条件变量上的一个线程。但是要注意的是条件变量只是起到阻塞和唤醒线程的作用具体的判断条件还需用户给出我这里给出的是tickets是否是偶数这个条件。