Linux—POSIX多线程管理-详解

还在编写中.....

多线程开发在 Linux 平台上已经有成熟的 Pthread 库支持。其涉及的多线程开发的最基本概念主要包含三点:线程,互斥锁,条件。其中,线程操作又分线程的创建,退出,等待 3 种。互斥锁则包括 4 种操作,分别是创建,销毁,加锁和解锁。条件操作有 5 种操作:创建,销毁,触发,广播和等待。其他的一些线程扩展概念,如信号灯等,都可以通过上面的三个基本元素的基本操作封装出来。


互斥锁是多线程编程中基本的概念,在开发中被广泛使用。其调用次序层次清晰简单:建锁,加锁,解锁,销毁锁。但是需要注意的是,与诸如 Windows 平台的互斥变量不同,在默认情况下,Linux 下的同一线程无法对同一互斥锁进行递归加速,否则将发生死锁


1、所谓递归加锁,就是在同一线程中试图对互斥锁进行两次或两次以上的行为。

这个问题与互斥锁的中的默认 recursive 属性有关。解决问题的方法就是显式地在互斥变量初始化时将设置起 recursive 属性。基于此,以上代码其实稍作修改就可以很好的运行,只需要在初始化锁的时候加设置一个属性。因此,建议尽量设置 recursive 属性以初始化 Linux 的互斥锁,这样既可以解决同一线程递归加锁的问题,又可以避免很多情况下死锁的发生。这样做还有一个额外的好处,就是可以让 Windows 和 Linux 下让锁的表现统一。

pthread_mutexattr_init(&attr); 
    // 设置 recursive 属性
    pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE_NP); 
    pthread_mutex_init(theMutex,&attr);
2、 等待的绝对时间问题

超时是多线程编程中一个常见的概念。例如,当你在 Linux 平台下使用 pthread_cond_timedwait() 时就需要指定超时这个参数,以便这个 API 的调用者最多只被阻塞指定的时间间隔。但是如果你是第一次使用这个 API 时,首先你需要了解的就是这个 API 当中超时参数的特殊性(就如本节标题所提示的那样)。

函数定义:

int pthread_cond_timedwait(pthread_cond_t *restrict cond, 
              pthread_mutex_t *restrict mutex, 
              const struct timespec *restrict abstime);

参数 abstime 在这里用来表示和超时时间相关的一个参数,但是需要注意的是它所表示的是一个绝对时间,而不是一个时间间隔数值,只有当系统的当前时间达到或者超过 abstime 所表示的时间时,才会触发超时事件。这对于拥有 Windows 平台线程开发经验的人来说可能尤为困惑。因为 Windows 平台下所有的 API 等待参数(如 SignalObjectAndWait,等)都是相对时间,假设我们指定相对的超时时间参数如 dwMilliseconds (单位毫秒)来调用和超时相关的函数,这样就需要将 dwMilliseconds 转化为 Linux 下的绝对时间参数 abstime 使用。

3、正确处理Linux平台下的线程结束问题

在 Linux 平台下,当处理线程结束时需要注意的一个问题就是如何让一个线程善始善终,让其所占资源得到正确释放。在 Linux 平台默认情况下,虽然各个线程之间是相互独立的,一个线程的终止不会去通知或影响其他的线程。但是已经终止的线程的资源并不会随着线程的终止而得到释放,我们需要调用 pthread_join() 来获得另一个线程的终止状态并且释放该线程所占的资源。

int pthread_join(pthread_t th, void **thread_return);

调用该函数的线程将挂起,等待 th 所表示的线程的结束。 thread_return 是指向线程 th 返回值的指针。需要注意的是 th 所表示的线程必须是 joinable 的,即处于非 detached(游离)状态;并且只可以有唯一的一个线程对 th 调用 pthread_join() 。如果 th 处于 detached 状态,那么对 th 的 pthread_join() 调用将返回错误。如果你压根儿不关心一个线程的结束状态,那么也可以将一个线程设置为 detached 状态从而来让操作系统在该线程结束时来回收它所占的资源。在任何一个时间点上,线程是可结合的(joinable),或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死在被其他线程回收之前,它的存储器资源(如栈)是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。将一个线程设置为 detached 状态可以通过两种方式来实现。一种是调用 pthread_detach() 函数,可以将线程 th 设置为 detached 状态。另一种方法是在创建线程时就将它设置为 detached 状态,首先初始化一个线程属性变量,然后将其设置为 detached 状态,最后将它作为参数传入线程创建函数pthread_create(),这样所创建出来的线程就直接处于 detached 状态。

创建 detach 线程:

    pthread_t       tid;

    pthread_attr_t  attr;

    pthread_attr_init(&attr);

    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    pthread_create(&tid, &attr, THREAD_FUNCTION, arg);

    总之为了在使用 pthread 时避免线程的资源在线程结束时不能得到正确释放,从而避免产生潜在的内存泄漏问题,在对待线程结束时,要确保该线程处于 detached 状态,否着就需要调用 pthread_join()函数来对其进行资源回收。 



Linux内核线程之深入浅出  :http://blog.163.com/jiams_wang/blog/static/303391492012103010374038/

Linux多线程——使用信号量同步线程:http://blog.csdn.net/ljianhui/article/details/10813469

Linux多线程——使用互斥量同步线程:http://blog.csdn.net/ljianhui/article/details/10875883

多线程编程注意事项:http://blog.csdn.net/l_yangliu/article/details/7104845

------------------------------------------------------------------一条华丽的分割线----------------------------------------------------------------------

int main(int argc,char* argv[])详解

   argc是命令行总的参数个数   
     argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数   
     命令行后面跟的用户输入的参数,比如:   
     int     main(int     argc,     char*     argv[])   
     {   
     int     i;   
     for     (i     =     0;     i<argc;     i++)   
     cout<<argv[i]<<endl;   
     cin>>i;   
     return     0;   
     }   
     执行时敲入   
     F:\MYDOCU~1\TEMPCODE\D1\DEBUG\D1.EXE     aaaa     bbb     ccc     ddd   
     输出如下:   
     F:\MYDOCU~1\TEMPCODE\D1\DEBUG\D1.EXE   
     aaaa   
     bbb   
     ccc   
     ddd   
--------------------------------------------------------------------
char     *argv[]是一个字符数组,其大小是int     argc,主要用于命令行参数     argv[]     参数,数组里每个元素代表一个参数;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值