79-多线程雷区

    xiaoxiao2021-03-25  111

    1. 问题提出

    相信你已经知道了多线程是怎么一回事了,现在你也可以用多线程去解决问题了。一般来说,互相之间没有严格执行顺序的问题,谁先谁后都无所谓,这种问题都可以使用多线程来解决。但是有时候,多线程会带来一些令人困挠的错误。先不管会产生什么问题吧,我们先来看我们的目标问题:

    程序员 allen 和 luffy 两人去抢火车票,很不幸的是,只剩下 3 张票了。现在请你起两个线程,去模拟抢票的过程。抢票过程:

    先查余票,如果有余票,下单将余票数量减 1有多少票抢多少票

    2. 问题解决

    假设我们使用全局变量 tickets 来表示数据库中余票的数量,接下来我们用程序 problem 来模拟此过程。

    2.1 程序清单

    // problem.c #include <unistd.h> #include <stdio.h> #include <pthread.h> int tickets = 3; void* allen(void* arg) { int flag = 1; while(flag) { // 从数据库中读取余票数,此操作假设消耗 20 ms int t = tickets; usleep(1000*20);// 20ms // 查看到余票数量 > 0,就打印 allen 买到一张票 if (t > 0) { printf("allen buy a ticket\n"); // 将余票数量减 1,再保存回数据库,此操作消耗 20 ms --t; usleep(1000*20);// 20ms tickets = t; } else flag = 0; // 买完票后,休息 20 ms usleep(1000*20);// 20ms } return NULL; } void* luffy(void* arg) { int flag = 1; while(flag) { int t = tickets; usleep(1000*20); if (t > 0) { printf("luffy buy a ticket\n"); --t; usleep(1000*20);// 20ms tickets = t; } else flag = 0; usleep(1000*20);// 20ms } return NULL; } int main() { pthread_t tid1, tid2; pthread_create(&tid1, NULL, allen, NULL); pthread_create(&tid2, NULL, luffy, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); return 0; }

    2.2 编译和运行

    $ gcc problem.c -o problem -lpthread $ ./problem

    2.3 结果及分析

    图 1 运行结果

    显然,上面的运行结果不是我们所期望的。你知道,系统中的余票只有 3 张。可是结果却显示 allen 和 luffy 各买了 3 张票!!!

    想象一下,如果这发生在 12306 上将多么可怕!其实你可以仔细想想,有时候你在 12306 上查的余票数还有 10 张,但是当你下单的时候,却发现票已售空了——空了——了。

    在我们这个例子中,会不会出现此种情况?当 luffy 在查看余票的时候,还有 3 张,可是当他下单的时候,说不定只剩下 2 张了。

    5. 总结

    知道多线程程序带来的问题理解为什么会出现这种错误

    本文是为后面的线程互斥和同步做铺垫,所以此问题的解决方案我们放到下一个专题中。

    转载请注明原文地址: https://ju.6miu.com/read-13393.html

    最新回复(0)