举两个程序实例,其中多线程不比单线程具有更好的性能

  1. 顺序程序,单线程具有更好的性能
  2. 空壳程序,类似c-shell和korn-shell,因为这样的程序和当前的工作空间联系非常紧密,如打开的文件、环境变量和当前工作目录

在什么情况下,采用多内核线程的多线程方法比单处理器系统的单线程,提供更好的性能?

当一个内核线程运行发生错误时,多内核线程可以中其他的内核会继续运行,如果时单线程的话,整个进程就会直接阻塞。所以当一个程序如果可能出现频繁的页面错误而不得不等待其他系统事件发生时,多线程方法会比单处理器系统的单线程提供更好的性能

在同一进程的多线程之间,下列哪些程序状态部分会被共享?

a. 寄存器值 b.堆内存 c.全局变量 d.堆栈内存

共享堆内存和全局变量,因为每个线程都有自己独立的寄存器和堆栈空间

在多处理器系统上采用多个用户级线程的多线程解决方案,比在单处理机系统上,能够提高更好的性能吗?

一个包括多用户线程的多进程系统无法在多处理器上同时使用不同的处理器。操作系统只能看到一个单一的进程,且不会调度在不同处理器上不同的进程的线程。因此多处理器系统执行多个用户线程是没有优势的。

第三章讨论了Google的Chrome浏览器,以及在单独进程中打开每个新网站的做法,如果Chrome设计成在单独线程中打开每个新网站,那么会有同样的好处吗?

不会,单独采用进程中打开每个新网站时,如果一个页面(进程)崩溃,并不会影响到其他的页面,而如果使用多线程,如果一个线程崩溃,那么可能导致整个浏览器崩溃。

有可能有并发,但无并行吗?

有可能,单核单线程就只能支持并发,但不支持并行,并行需要多线程

设计一个应用,其60%为并行部分,而处理核数量分别为(a)2个和(b)4个,利用Amdahl定律,计算加速增益

a:​\(\frac{1}{0.4+\frac{1-0.4}{2}}\approx 1.43\)

b:​\(\frac{1}{0.4+\frac{1-0.4}{4}}\approx 1.82\)

确定下列问题是任务并行性还是数据并行性

  • 习题4.16所述的多线程统计程序(数据并行性)
  • 本章项目1所述的多线程的Sudoku验证器(任务并行性)
  • 本章项目2所述的多线程排序程序(数据并行性)
  • 4.1节所述的多线程Web服务器(任务并行性)

具有2个多核处理器的系统有4个处理器可用于调度,这个系统有一个CPU密集型的应用程序运行,在程序启动时,所有的输入通过打开一个文件而读入。同样,在程序终止之前,所有程序输出结果,都写入一个文件。在程序启动和终止之间,该CPU为密集型的,你的任务是通过多线程技术来提高这个应用程序的性能,这个应用程序运行在采用一对一线程模型的系统(每个用户线程映射到一个内核线程)

  • 你将创建多少个线程,用于执行输入与输出?线程数取决于应用程序的要求,因此一个线程就够了
  • 你将创建多少个线程,用于应用程序的CPU密集型部分?线程数和处理核应该是一样的,应该需要四个线程

考虑下面的代码段

pid_t pid;
pid = fork();
if(pid == 0) { \*child process*\
    fork();
    thread_create(...);
}
fork();
  • 创建了多少个单独的线程?两个:首先fork(),创建一个子进程,在子进程中由于pid为零,所以会进入到if中,在if中,子进程又创建了一个子进程,这个时候第二个子进程创建一个线程,然后第一个子进程会创建一个线程,所以是两个。
  • 创建了多少个单独的进程?首先fork(),创建一个子进程ans=1,然后子进程进入if,再进行了fork()创建子进程ans=2,第二个子进程在退出if后,会执行fork(),所以ans=3,第二个子进程结束,然后第一个子进程退出if后执行fork(),ans=4,所有子进程结束,父进程因为pid不为零,所以不能进入if,最终执行fork(),ans=5。所以一共创建了五个进程

如4.7.2节所述,Linux并不区分进程和线程。相反,Linux采用相同的方式对待他们;根据系统调用clone()传递标志组合,一个任务可能类似于一个进程或一个线程。然而,其他操作系统,如Windows,区别对待进程和线程。通常,对这类系统,每个进程的数据结构会包含同属该进程的多个线程的指针。比较内核的进程与线程这两种建模方法。

一方面,线程和进程在系统中被认为是相似的,有些系统代码可以简化,比如,一个调度器可以在平等的基础上考虑不同的线程和进程,且不需要特殊的代码就可以在调度中审查有关线程的进程。另一方面,这种统一会使进程资源限制更加困难。

如图所示的程序使用Pthread API,该程序的LINE C和LINE P的输出分别是什么

#include<pthread.h>
#include<stdio.h>

int value = 0;
   
void * runner(void * param) {
    value = 5;
    pthread_exit(0);
}
int main(int argc, char * argv[]) {
    pid_t pid;
    pthread_t tid;
    pthread_t attr;
    
    pid = fork();
   	
    if(pid == 0) { /*子进程*/
        pthread_attr_init(&attr);
        pthread_create(&tid, &attr, runner, NULL);j
        pthread_join(tid, NULL);
        printf("CHILD:value = %d", value); /*LINE C*/ 
    } else if(pid > 0) {
		wait(NULL);
        printf("PARENT:value = %d", value);  /*LINE P*/ 
    }
    
    return 0;
}

//不知道为啥在Linux下编译不通过...所以是我直接分析的。。

LINE C:CHILD:value = 5

LINE P:PARENT:value = 0

设有一个多核系统和一个多线程程序,该程序采用多线程模型来编写,设系统内的用户级线程数大于处理核数量,讨论以下情况对性能的影响

  1. 分配给程序的内核线程数量小于处理核数量
    1. 系统中一些处理核处于空闲状态,因为调度图中只有内核线程的处理器,而没有用户线程的处理器
  2. 分配给程序的内核线程数量等于处理核数量
    1. 所有处理核同时使用,然而,如果一个内核块内的内核因页面错误或同时援引系统调用时时,相应的处理器将闲置
  3. 分配给程序的内核线程数量大于处理核数量,但小于用户线程数量
    1. 封锁一个内核线程并调出,换入另一个准备执行的内核线程,因此,可以增加处理器系统的利用率