我有以下问题陈述:
实现一个函数substLinesMany ....应同时处理所有指定的文件。如果任何文件导致错误,则substLinesMany将返回false,否则返回true。
你会在这里使用线程或分叉吗? (必须选一个)
答案 0 :(得分:4)
我会使用线程分叉。创建新线程比创建新进程消耗的资源更少。线程共享相同的地址空间,而分叉进程需要使用新的地址空间创建新进程。鉴于函数的性质(替换文件中的行),不需要为每个文件分配一个地址空间。
唯一的缺点是,在使用线程时可能会遇到同时打开文件的数量可能存在每个进程的限制。但这是一个可控制的问题。
答案 1 :(得分:2)
不同意见,以防万一。由于@CraigAnderson提到的优势,线程似乎很诱人。
但不要忘记以下事实:
线程非常困难。共享内存意味着您必须使用锁等保护关键代码和数据部分。这是调试的噩梦。
轶事证据表明,在大多数情况下,您的并行解决方案将比顺序解决方案慢。原因是:缓存未命中。内存比CPU慢。如果所有线程一直访问所有进程内存,那么所有CPU都会花时间刷新缓存。
fork
的开销远低于您的想象。 Linux是copy-on-write,因此子进程以与父进程相同的物理内存页开始。只有更改的数据才会触发编写新的物理页面。
当你将线程与分叉进行比较时,你隐含地假设一个Unix操作系统。线程在非Unix系统(Windows)上非常有用,在这些系统中,进程创建是一个巨大的开销。
并行程序需要仔细设计,其中每个线程/进程仅在其自己的内存块上工作,以最大限度地减少缓存未命中。所以你会发现使用分叉和一些Unix流IPC是非常有效的,具有最小的开销并且更容易调试。
Unix IPC的语义,特别是管道,提供了一种优秀且易于使用的进程间通信方式。例如,来自工人子管道的read
阻塞,直到结果可用。在父级中添加select
循环,您可以与简单的read
进行数据交换和同步。
线程比分叉更不便携。如果您使用uClibc库而不是glibc处理多核嵌入式系统,那么uClibc没有线程。
参考文献:
正如你在参考文献中看到的那样,他们都是大牌:ESR,Ousterhout,Larry Wall,Brendan Eich,StackOverflow的创始人。比我更聪明的程度,仍然吓坏了线程。