进程是系统中程序执行和资源分配的基本单位。每个进程有自己的数据段、代码段和堆栈段。
线程通常叫做轻型的进程。线程是在共享内存空间中并发执行的多道执行路径,他们共享一个进程的资源。
线程和进程比起来很小,所以相对来说,线程花费更少的CPU资源。
2.如何来标识一个线程?
表示进程号的为pid_t类型,表示线程号的是pthread_t类型; pthread_t是一个结构体而不是整型;
使用pthread_equal确定两个线程号是否相等;
使用pthread_self函数来获取线程的ID;
3.线程是如何创建和退出的?
创建线程使用pthread_create函数。在线程创建以后,就开始运行相关的线程函数。
线程退出时使用函数pthread_exit,是线程的主动行为。注意进程退出时使用exit函数,线程中用pthread_exit替代exit。
由于一个进程中的多个线程共享数据段,因此通常在线程退出后,退出线程所占用的资源并不会随线程结束而释放。所有需要pthread_join函数来等待线程结束,类似于wait系统调用。
4. 如何实现单个线程的退出?
如果一个线程调用了exit, _Exit, 或者_exit,将导致整个进程的终止。要实现单个线程的退出,可以采用如下方式:
(1) 线程可以简单的从start routine返回,返回值就是线程的退出代码。
(2) 线程可以被同一进程中的其它线程终止。
(3) 线程调用pthread_exit
5.如何使调用线程阻塞等待指定线程的退出,并获得退出线程的返回码?
调用线程将会被阻塞直到指定的线程终止。如果线程简单的从start routine返回则rval_ptr将包含返回代码。如果线程是被撤销(调用pthread_exit)的,rval_ptr指向的内存地址将被设置为PTHREAD_CANCELED.
通过调用pthread_join,我们自动的将一个线程变成分离状态,这样就可以实现资源的回收。如果线程已经处于分离状态,调用pthread_join将会失败,并返回EINVAL。
如果我们对于线程的返回值不感兴趣,可以将rval_ptr设置成NULL。 值得注意的是,pthread_create和 pthread_exit函数的无类型指针可以传递复杂的结构信息,但这个结构所使用的内存在调用者完成后必须仍然有效(分配在堆上或者是静态变量),否则就会出现使用无效的错误。
6.如何通过一个线程让另外一个线程退出?
调用pthread_cancel函数将导致tid所指向的线程终止运行。但是,一个线程可以选择忽略其它线程控制该线程何时退出。注意,该函数并不等待线程终止,它仅仅提出要求
7.如何实现线程退出时的清理动作?
线程可以建立多个清理处理程序,这些程序记录在栈中,也就是说他们的执行顺序与注册顺序想法。使用如下函数注册清理函数:
void pthread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_cleanup_pop(int execute);
rtn将被调用,并传以arg参数,引起该函数调用的情况如下:
1.调用pthread_exit
2.对于退出请求的反应
3.以非0参数调用pthread_cleanup_push
如果pthread_cleanup_pop的参数非0则仅仅移除该处理函数而不执行。
如果函数已经处于分离状态,则当它退出时线程底层的存储资源会被立即回收。处于分离状态的线程,如果调用pthread_join来等待其退出将会出现错误。
8.Linux下提供那些方式处理线程同步?
Linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和信号量。
9.什么情况会发生线程死锁,如何避免死锁?
如果一个线程对mutex加两次锁则显然会导致死锁。 死锁可以通过控制加锁的顺序来避免。有两个mutex A和B,如果所有的线程总是先对A加锁再对B加锁就不会产生死锁。但实际应用中可能很难保证这种顺序加锁的方式,这种情况下,可以使用pthread_mutex_trylock来避免死锁的发生。
10.什么是条件变量,它有什么作用?
条件变量是线程可用的另外一种同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定条件的发生。条件本身是由互斥量保护的。线程在改变状态前必须首先锁住互斥量,其它线程在获得互斥量之前不会觉察到这种变化。