问题
知友(知乎网站)问:多线程读写socket导致的数据混乱的原因是什么? 这确实是许多初学网络(socket)编程的同学容易迷糊的地方。
这个问题在生活中可以找到许多极其相似的例子,比如打电话,或者排队。
以下是南老师的回答。
《白话C++》 的例子
正好《白话C++》有讲到这个。发送方 发送的报文内容是: “亲爱的,你不胖不瘦真真美啊!”。
按次序,这句子自然是这么发送过去的:
[发送方]---- !啊美真真瘦不胖不你,的爱亲 ---> [接收方]
如果接收方那边是一位小姑娘(我猜是),并且是一位喜欢并发处理事情的,利索的小姑娘。她启了三个线程同时读取,就可能读成这样:
- 第一个读取到:“亲,你不瘦真美”;
- 第二个读取到:“爱的不真啊”;
- 第三个读取到:“胖!”
(摊手:)小姑娘觉得男友和她说了三句话。
书中下面这张图:
解读
并发写造成写入的数据混乱的原因
图中的上半部分:两个线程并发的写。两个线程都在一个字符一个字符地写,一个负责写数字,一个负责写字母,但收到的数据是数字与字母夹杂的字符串。
很好理解:把一个socket连接理解为一条队列,数字理解为一边是男生堆,字母理解为另一边是女生堆;一声令下,两边的人都拼命地往队列里跑过去排队,自然就是男生女生会混在一起。
并发读造成读到的数据混乱的原因
图中下半部分:一份数据、一个连接(或一个socket),多个线程并发的读(图中是三个线程),假设没有按照某种策略读,仅是纯按某个瞬间,数据到达的次序读取,结果就是三个线程各自读了一些数据,谁都没读完整,仿佛是一道密文,被三人分别领取,结果谁也没明白自己读到的是什么。