文章目录
  1. Questions
  2. 线程
    1. 线程基础
    2. 线程安全

Questions

(1)程序为什么要被编译器编译之后才能运行?

(2)编译器是如何将C语言程序转化成可执行的机器码的?

(3)可执行文件中有哪些内容,它们是如何组织的?

(4)解释#include<stdio.h>的作用,C语言库是什么?要如何实现?

(5)不同的编译器、硬件平台以及操作系统,编译同一源代码的结果是否相同?为什么?

(6)一个程序是如何运行的?(如何装载、从哪里执行、到哪里结束、结束之后又会发生什么)

(7)一个程序在没有操作系统的机器上如何才能运行?

(8)printf函数是如何实现的?

(9)程序在运行时,它在内存中的组成?

在学习完《程序员的自我修养》之后,对上述问题的回答

线程

线程基础

可抢占线程与不可抢占线程:线程在时间片用尽之后,被操作系统剥夺继续执行的权利而进入就绪状态,这个过程称为抢占。在早期的操作系统中,线程是不可抢占的,只有运行的线程主动发出放弃执行的命令,才能让其他就绪态线程获得CPU。

线程安全

信号量、互斥量、临界区:信号量可以跨进程使用,允许一个或多个线程访问共享资源,可以被任意线程申请与释放;互斥量可以跨进程使用,资源在任何时刻最多被一个线程占用,但是只有获取了互斥量的线程可以释放互斥量;临界区作用于进程内部,临界区中的资源在任何时刻最多被一个线程占用。

可重入:一个函数在未执行完的情况下,由于外部因素或内部调用,又一次进入自身执行。一个函数称为可重入的,即该函数被重入后不会产生任何不良后果。需满足如下条件:

  • 不使用任何(局部)静态或全局的非const变量;
  • 不返回任何(局部)静态或全局的非const变量的指针;
  • 仅依赖于调用方提供的参数;
  • 不依赖任何单个资源的锁;
  • 不调用任何不可重入的函数;

过度优化:编译器在优化时,为了提高效率而交换两条互不相关的指令的执行顺序。CPU的动态调度技术,在执行程序时为提高效率而交换两条指令的执行顺序。

为解决这些优化而导致的多线程错误。在代码中加入volatile关键字阻止过度优化,它可以做到两件事:(1)阻止编译器为了提高运行速度将一个变量缓存到寄存器而不写回;(2)阻止编译器调整volatile变量的指令顺序。

CPU提供barrier指令,一条barrier指令指令阻止CPU将该指令之前的指令交换到barrier,反之亦然。