Skip to content

败犬日报 2025-04-29

1. 同一个 shared_ptr 的复制移动 reset 等操作不是线程安全的

(这个话题仔细一想其实很显然)

shared_ptr 使用了原子变量,可能会被误以为同一个 shared_ptr 复制移动是线程安全,实则不然。

例如,A 线程 reset 把引用计数减到 0,然后析构;B 线程恰好在析构前拷贝,就会获得已析构的非法对象,代码如下:

cpp
shared_ptr<int> a;
// 线程 A
a.reset(new int);
// 线程 B
auto b = a;

shared_ptr 的原子变量目的是保证不同 shared_ptr 的并发安全,重点是“不同”。

同一个 shared_ptr 复制、移动、reset 等操作想要线程安全,只靠引用计数的几个原子变量是不行的,需要额外结构。这也是 atomic<shared_ptr> 做的事情。

2. 经典劣质八股之 TCP “粘包”问题

TCP 是面向流的协议,没有“包”的概念。所谓的“包”是应用层划分的,那就应该应用层负责处理,完全不关 TCP 的事。

所以不构成问题。

可惜的是直到今天还有面试官会这个问题。

3. debug 没问题 release 会段错误

很可能是未定义行为。

可以编译一个 RelWithDebInfo 版本看看。

4. 多生产者多消费者,竞争激烈怎么办

要尽量规避竞争,一种容易实现的方式是分 shard + 异步(每个线程一个队列,任务通过哈希来分发)。

除此之外就是一个好的 MPMC queue 了,可以看下 folly 或 rigtorp 的实现。把 rigtorp 的 MPMC Queue 复制粘贴一下,改成 flexible array,丢到 shm 上即可。

(免责:这部分我不懂)