多线程 - 基本知识

来源:互联网 发布:网络侦探 进化表 编辑:程序博客网 时间:2024/05/20 02:57

线程和进程区别

进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应得并发性。进程和线程的区别在于:

一个程序至少有一个进程,一个进程至少有一个线程。

线程的划分尺度小于进程,使得多线程程序的并发性高,另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。


函数可重入

我的理解:可重入函数,与多线程无关,即可重入概念并不依赖于多线程,可重入的提出时依据单一线程提出来的,当然,多线程可重入是他的扩展。一个函数被同一个线程调用2次以上,得到的结果具有可再现性(多次调用函数,得到的结果是一样的)。那么我们说这个函数是可重入的。

可重入,并不一定要是多线程的。可重入只关注一个结果可再现性。在APUE中,可函数可重入的概念最先是在讲signal的handler的时候提出的。此时进程(线程)正在执行函数fun(),在函数fun()还未执行完的时候,突然进程接收到一个信号sig, 此时,需要暂停执行fun(),要转而执行sig信号的处理函数sig_handler(),那么,如果在sig_handler()中,也恰好调用了函数fun().信号的处理是以软终端的形式进行的,那么,当sig_handler()执行完返回之后,CPU会继续从fun()被打断的地方往下执行。这里讲的比较特殊,最好的情况是,进程中调用了fun(),函数,信号处理函数sig_handle()中也调用了fun()。如果fun()函数是可重入的,那么,多次调用fun()函数就具有可再现性。从而,两次调用fun()的结果是正确的预期结果。非可重入函数,则恰好相反。

简而言之,可重入函数,描述的是函数被多次调用但是结果具有可再现性。

如果fun(),中,使用了static变量、返回全局变量、调用非可重入函数等等,带有全局性的操作,都将会导致2次以上调用fun()的结果的不可再现性(当然,有些时候使用了static、全局变量等等,不一定导致调用结果不可再现性)。只要使调用结果具有可再现性,那么该函数就是可重入的。

为了保证函数是可重入的,需要做到一下几点:

1,不在函数内部使用静态或者全局数据

2,不返回静态或者全局数据,所有的数据都由函数调用者提供

3,使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据

4, 如果必须访问全局数据,使用互斥锁来保护

5,不调用不可重入函数


线程安全

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。

线程安全问题都是由全局变量及静态变量引起的。

若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。

线程安全,是针对多线程而言的。那么和可重入联系起来,我们可以断定,可重入函数必定是线程安全的,但是线程安全的,不一定是可重入的。不可重入函数,函数调用结果不具有可再现性,可以通过互斥锁等机制,使之能安全的同时被多个线程调用,那么,这个不可重入函数就是转换成了线程安全。


线程同步

1. 互斥锁/读写锁

2. 信号量

3. 条件变量

4. 原子操作

具体怎么使用这些同步方法,请查阅其他资料。


原创粉丝点击