多线程 的基本概念

      太多的学长告诉我,一个优秀的开发人员必须对线程有一个详细的了解。没办法,硬着头皮上吧。

线程的基础知识:首先,线程是系统内核对象之一。那么先介绍一下内核对象。

1.内核对象:是系统内核分配的一个内存块,该内存结构描述的是一个数据结构,其成员负责维护对象的各种信息,内核对象的数据只能由系统内核来访问,应用程序无法再内存中找到这些数据结构并直接改变其内容。常用的内核对象有:事件对象,文件对象,作业对象,互斥对象,管道对象,进程对象和线程对象等。不同类型的内核对象,其数据结构各不相同,但是也有一些共有的属性。

         内核对象具有引用计数属性。内核对象在进程中创建,但不被进程所拥有。当创建一个内核对象时,内核对象的引用计数为1,当其他进程访问该内核对象时,引用计数将递增1;当内核对象的应用计数为0时,系统内核将自动撤销该对象,这就意味着,如果在一个进程中创建一个内核对象,在其他进程中访问了该内核对象,当创建内核对象的进程结束时,内核对象未必会释放,只有当内核对象的引用计数为0时才会被释放。

         内核对象还具有安全属性,用安全描述符来表示。安全描述符描述了谁创建了该内核对象、谁有权访问或使用内核对象,以及内核对象是否能够被继承等信息。

        对于系统中的每一个线程,操作系统都会为其分配相应的时间片,使这些线程轮换执行,由于时间片都非常的短,因此在用户看来就像是多个线程同时运行,如图为cpu为线程分配时间片的状态:

一般来说:线程是代码的执行路径,每一个线程都关联一个线程函数,在线程创建时设置,线程存在三种状态,挂起,唤醒和终止。而它的执行过程为:如果创建线程时挂起线程,则该线程会暂时停止执行线程函数,直到用户唤醒线程,如果线程创建没有挂起线程,则会立即执行线程函数,当线程函数执行完毕后,该线程就终止了(不会再被cpu去执行了)。

下面是线程的基本操作函数(API):

1.线程的创建: CreateThread(),函数执行成功返回,线程句柄,否者返回NULL.。

2.线程的调度:在创建线程时可以指定线程是否立即运行,如果线程没有运行,则表示线程当前处于挂起状态。为了运行线程函数,可以通过唤醒线程来实现。为了能够对运行中的线程进行控制,用户也可以挂起一个运行的线程,在需要的时候,重新唤醒。 下面就是相关的函数。

1)SuspendThread(HANDLE hThread) 函数,用于挂起线程。参数为线程句柄

2)ResumeThread(HANDLE hThread)函数,用于减少线程挂起的次数,如果线程挂起的次数为0,将唤醒线程。

3)ExitThread(DWORD dwExitCode)函数,表示线程退出(参数为:线程退出代码)。

4)TerminateThread(HANDLE hThread,DWORD dwExitCode)函数,该函数用于强制终止线程的执行。

3.线程的同步技术:在多线程应用程序中,由于每个线程都可以访问进程中的资源,这样有可能导致危险。(例如:线程A正在使用一个对象,而线程B对这个对象进行了修改,导致线程A的执行结构不可预料,所以解决这个问题,通过线程同步来解决资源访问冲突问题)。

<1> 事件对象实现线程同步:事件对象属于系统内核对象之一,在进行线程同步时,经常使用事件对象来实现。事件对象可以分为两类,即人工重置事件对象 和 自动重置事件对象。     对于人工重置事件对象,可以同时有多个线程等待到事件对象,成为可调度线程。 对于自动重置对象,等待该事件对象的多个线程只可能有一个线程成为可调度线程,此外,如果事件对象为自动重置事件对象,当某个线程等待到事件对象后,系统 将自动将事件对象设置为未通知状态。

为了使用事件对象,系统提供了一组与事件对象相关的函数(API):

1)CreateEvent()函数:用于创建一个事件对象。      执行过后的事件状态:??

2)SetEvent(HANDLE  hEvent);参数表示事件对象句柄。该函数用于将事件设置为通知状态。

3)ResetEvent(HANDLE hEvent);该函数将事件设置为未通知状态。

4)WaitForSingleObject ()函数:该函数用于等待内核对象的状态。      执行过后的事件状态:??

<2> 互斥对象实现线程同步:互斥对象能够使线程拥有某个资源的绝对访问权。互斥对象主要包含使用数量,线程ID和递归计数器等信息。线程ID表示当前拥有互斥 对象的线程;递归计数器表示线程拥有互斥对象的次数。互斥对象的使用方法为:当互斥对象的线程ID为0时,表示互斥对象不被任何线程所拥有。此时系统会发 出该互斥对象的通知信号,等待互斥对象的某个线程将会拥有该互斥对象,同时互斥的线程ID为,拥有该互斥对象的线程ID。当互斥对象的线程ID不为0时, 表示当前有线程拥有该互斥对象,此时系统不会发出互斥对象的通知信号,其他等待互斥对象的线程将继续等待,知道拥有互斥对象的线程释放互斥对象的拥有权。

相应的函数:

1)CreateMutex():用于创建一个互斥对象。

2)ReleaseMutex(HANDLE hMutex);  参数用于释放互斥对象的所有权,参数表示互斥对象的句柄。


练习:

1.在自己的应用程序中调用QQ。    (考察进程的创建)。

2.利用多线程实现文件的查找。  (在线程中调用的,文件查找函数,因为文件查找比较费时,无法实时响应界面的操作,所以开辟了一个线程进行操作)(毫无感觉)。

3.禁止程序重复运行。(通过在初始化时,创建互斥对象,来实现)。

4.垃圾文件清理工具(说实话,通过这几个小项目的实现过程中,我发现,线程中代码的量是很小的,也就是说,线程中只是一般的调用了全局的函数,本身操作是很少的,看样子得找个复杂一点的练练手啊)。

5.利用多线程实现文件下载(通过项目的实现后,我知道了,其中,只是以下载文件的大小来决定,开线程的个数,但是各个线程间是没有任何关系的,而且里面主要是在调用API函数,线程的操作只是,开了一个记录句柄的线程数组,然后,就没有然后了。)(失望)


以上就是对线程的基本只是的了解了,这种东东,还是要在实践中加深认识的,未完待续。。。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值