• 线程基础、线程调度


    1、线程的两个组成部分:线程的内核对象(管理线程和使用计数)、线程栈(用于维护线程执行时所需的函数参数和局部变量)

    2、线程函数

      线程函数可以任意命名;

      线程函数只有一个参数;

      线程函数必须返回一个值,它会成为该线程的退出代码;

      线程函数应尽可能使用函数参数和局部变量;

    3、线程终止运行时:

      线程拥有的所有用户对象(窗口、挂钩)会被释放,其他对象只有在拥有线程的进程终止时才被销毁;

      线程的退出代码(在内核对象中维护)从STILL_ACTIVE变成传给ExitThread或TerminateThread的代码;

      线程内核对象的状态变为触发状态;

      如果线程是进程的最后一个活动线程,系统则认为进程也终止了;

      线程内核对象的使用计数递减1;

    4、线程的上下文:一组CPU寄存器,最重要的两个寄存器是指令指针寄存器IP和栈指针寄存器SP,IP被设为线程函数地址在线程堆栈中的地址,SP被设为RtlUserThreadStart函数的地址,该函数会调用ExitThread和ExitProcess函数  

    5、在多线程环境中C/C++运行库的变量和函数会出问题,为保证多线程程序正常运行,必须创建一个数据结构,并使之与使用了C/C++运行库函数的每个线程关联,然后在调用C/C++运行库函数时,那些函数必须知道去查找主调线程的数据块,从而避免影响到其他线程

    6、_beginthreadex函数:

      每个线程都有自己的专用_tiddata内存块,它们是从C/C++运行库的堆上分配的;

      传给_beginthreadex的线程函数的地址保存在_tiddata内存块中;

      _beginthreadex会在内部调用CreateThread;

      CreateThread函数被调用时,传给他的函数地址是_threadstartex(而非pfnStartAddr),参数地址是_tiddata结构的地址(而非pvParam);

      成功返回线程句柄,失败返回0

    7、_threadstartex函数:

      新的线程先执行RtlUserThreadStart,再跳转到_threadstartex;

      _threadstartex唯一参数是新线程的_tiddata内存块的地址;

      _threadstartex函数将_tiddata内存块与新建线程关联起来,调用操作系统函数TlsSetValue(线程局部存储TLS);

      无参数的辅助函数_callthreadstartex中有一个SEH帧,它将预期要执行的线程函数包围起来;

      预期要执行的线程函数会被调用,其地址和参数会在_callthreadstartex中从TLS中获取;

      _callthreadstartex中调用_endthreadex函数,最后返回到_threadstartex,继而到RtlUserThreadStart,线程终止运行

    8、_endthreadex函数

      函数将_tiddata内存块释放,再调用ExitThread函数销毁线程,并传递设置线程的退出代码

    9、使用CreateThread创建线程会导致的问题:

      线程如果使用C/C++运行库的signal函数,则整个进程都会终止,因为结构化异常处理SEH帧没有就绪;

      线程如果不是通过调用_endthreadex来终止,则数据块就不能被销毁,从而导致内存泄漏     

    10、线程的挂起和恢复:SuspendThread、ResumeThread

    11、Sleep函数将使线程自己挂起一段时间:

      系统设置线程不可调度时间只是近似于所设定的毫秒数;

      参数传入INFINITE时告诉系统永远不要调度该线程,传入0时是强制系统调度其他线程

    12、GetThreadTimes函数可返回线程的创建时间、退出时间、内核时间、用户时间,线程执行时间 = 内核时间+用户时间

      GetProcessTimes类似GetThreadTimes,返回时间适用于一个指定进程中的所有线程所耗时间的总和

    13、系统使用CONTEXT结构记住线程的状态,这样线程在下一次获得CPU可以运行时,就可以从上次停止处继续。

      GetThreadContext函数只能返回线程的用户模式上下文,可以查看线程的任何寄存器值,再调用该函数前应先调用SuspendThread         

  • 相关阅读:
    Redis on Spark:Task not serializable
    一次Spark应用程序参数优化案例
    Spark性能优化(2)——广播变量、本地缓存目录、RDD操作、数据倾斜
    Spark性能优化(1)——序列化、内存、并行度、数据存储格式、Shuffle
    Java – Convert IP address to Decimal Number
    Java IP地址字符串与BigInteger的转换, 支持IPv6
    Spark性能优化(2)——广播变量、本地缓存目录、RDD操作、数据倾斜
    Android Matrix类以及ColorMatri
    OpenGL中shader使用
    Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析 .
  • 原文地址:https://www.cnblogs.com/yapp/p/11594581.html
Copyright © 2020-2023  润新知