1000 位游戏用户,多进程 OR 多线程?
2021-09-20 14:11:18

这是我曾在一次实习面试中遇到的问题

现在游戏中有 1000 位游戏用户,用多进程编程还是多线程编程?为什么?

当时我的想法

明确了一下问题性质,应当是进程和线程的区别问题,涉及到优劣。我最先想到的是:同一进程下,如果有线程崩溃,会影响到其他线程,进而导致整个进程崩溃。所以当时给面试官的回答是使用多线程,并给出了自己的理由

与朋友讨论

今天和朋友讨论到这个问题,他们提出了一些要点,我也想到了一些问题

首先说说我想到的,这应当涉及到线程模型的问题

  1. 如果说线程崩溃影响到进程,那这应当是用户级线程模型:进程下的多个用户级线程共享一个内核级线程。从效率来说不合适,CPU 数太少了
  2. 使用我回答的多进程,每次切换进程时都要进内核态,消耗太大
  3. 需要考虑到:同一个进程下的多线程共享资源;多进程之间需要解决资源共享问题

朋友也提到一个问题:如果用多进程,那用户数扩大到十万时,端口数怎么解决?

基于这些问题,我重新思考了一下,以 DNF 为例,提出一个新观点:

  1. 每个游戏大区对应一个进程,在这个进程(游戏大区)中,线程(用户)共享进程的资源(副本记录、公会信息、交易行信息等),线程保存自己的资源(用户数据)
  2. 线程模型采用混合实现:n 个内核级线程对应进程下的 m 个用户级线程(n < m)。这样在进程中,可以同时有多个线程工作,提高工作效率;当某个线程崩溃时,不会影响到整个进程

记录问题时查找资料

在晚上记录这个问题时,查找了一些关于游戏服务器的资料,我突然发现:游戏服务器并不是用一个进程或线程解决一个用户的所有操作,而是依靠多进程或多线程来分门别类的处理不同用户的相同操作

同时,在涉及到多线程时,还应当考虑锁的同步问题。而加锁解锁的操作也会浪费 CPU 资源,多进程不需要加锁

但是转念一想:数据不可能像当时想的那样全放在进程中,而是放在数据库中。读操作还好说,写操作一样涉及到锁

一想到数据库,又想到:怎么可能用线程来保存用户数据,不然用户下线了线程还不能释放资源,要一直等着用户上线才能使用,太浪费了。应当是保存用户数据到数据库中,用户下线了以后初始化线程,给新上线的用户使用

(麻了,好复杂 😅