用Posix thread进行多线程设计,就不怕跨平台了,因为很多OS都兼容Posix thread,如Linux/Windows等,甚至嵌入式系统上(如rt-thread)都支持posix thread API。线程有比进程体积小,速率高,速度快等优势。所以编程时,如果涉及到效率和速度时,采用pthread_create()一个线程总比 fork()一个进程好些。

Posxi thread 线程操作主要有创建(creation),终止(termination),同步(joins,blocking),调度(scheduling),数据管理(datamanagement)和交互(interaction).

可以从以下线程框图了解线程的构架:

多线程间关系:

多线程间共享内存模型:

与普通的fork()进程不一样,线程很简单,线程并不需要维护线程列表,也不需要知道谁创建了它。以下是pthread_create()与fork()在各种平台上,性能的比较:

  • The primary motivation for using Pthreads is to realize potential program performance gains.
  • When
    compared to the cost of creating and managing a process, a thread can
    be created with much less operating system overhead. Managing threads
    requires fewer system resources than managing processes.

For example, the following table compares timingresults for the fork() subroutineand the pthread_create() subroutine.Timings reflect 50,000 process/thread creations, were performed with the time utility, and units are in
seconds, nooptimization flags.

Note: don't expect the sytem and user times toadd up to real time,
because these are SMP systems with multiple CPUs workingon the problem
at the same time. At best, these are approximations run on
localmachines, past and present.

Platform

fork()

pthread_create()

real

user

sys

real

user

sys

Intel 2.8 GHz Xeon 5660 (12cpus/node)

4.4

0.4

4.3

0.7

0.2

0.5

AMD 2.3 GHz Opteron (16cpus/node)

12.5

1.0

12.5

1.2

0.2

1.3

AMD 2.4 GHz Opteron (8cpus/node)

17.6

2.2

15.7

1.4

0.3

1.3

IBM 4.0 GHz POWER6 (8cpus/node)

9.5

0.6

8.8

1.6

0.1

0.4

IBM 1.9 GHz POWER5 p5-575 (8cpus/node)

64.2

30.7

27.6

1.7

0.6

1.1

IBM 1.5 GHz POWER4 (8cpus/node)

104.5

48.6

47.2

2.1

1.0

1.5

INTEL 2.4 GHz Xeon (2 cpus/node)

54.9

1.5

20.8

1.6

0.7

0.9

INTEL 1.4 GHz Itanium2 (4 cpus/node)

54.5

1.1

22.2

2.0

1.2

0.6

在同一个线程或进程中所创建的线程共同享有一样的地址空间。

线程间共享:

.进程指令(process instructions)

.大部分数据(most data)

.文件(descriptors)

.信号和信号句柄(signals and signal handlers)

.当前工作目录(current working directory)

.用户和组id(user and group id)

线程独自属性:

.线程id(thread id)

.寄存器(内容)和栈不同(set of registers,stack pointer)

.局部变量,返回地址(stack for local variables,return addresses)

.信号mask(signal mask)

.优先级(priority)

.返回值(return value errno)

主要的操作函数:

/*创建一个线程,成功返回0,失败返回error错误标志*/

  1. int pthread_create(pthread_t * thread,            //thread :线程id, unsigned long intxi型
  2. const pthread_attr_t *attr,       //attr: 线程属性参数,创建时将根据这个参数进行线程初始化
  3. void *(*start_routine)(void *), //start_routine:指向线程所调用的函数
  4. void *arg);                                //arg :线程传递参数

/* 终止线程,成功返回0,失败返回error错误 标志*/

  1. void pthread_exit(void *retval);      //retval:返回值指针

/*等待直到id为th线程运行结束(合并一个线程的意思)*/

  1. int pthread_join(pthread_t th, void**thread_return);  // th:线程id
  2. // thread_return :线程终止或取消时的返回值指针

/*获取当前线程id*/

  1. pthread_t pthread_self(void);

线程的同步机制:

.互斥量(mutexes)

.连接/合并(joins)

.条件变量(condition variables)

/*线程间互斥量操作函数,顾名思义*/

  1. int pthread_mutex_lock(pthread_mutex_t*mutex);//获取mutex,成功返0,失败返回错误标志,并阻塞当前线程
  2. intpthread_mutex_trylock(pthread_mutex_t *mutex); //同上,不同的是多了个try(也就是说先try一下)
  3. //如果在当前线程中,如果同一个互斥量已经被当前线程锁住,pthread_mutex_tyrlock将立即返回(成功).如果互斥量类型为:PTHREAD_MUTEX_RECURSIVE那么mutexlock count将自加一,然后立即返回(成功)
  4. int pthread_mutex_unlock(pthread_mutex_t*mutex);   //释放一个mutex

实现原理:互斥量用于多线程对临界资源的访问,通过mutex lock
count来判定是否锁住,初始值为0,当pthread_mutex_lock时mutex lock_count
自加,pthread_mutex_unlock时将mutex_lock_count自减。所以互斥量可用时mutex_lock_count =
0,对于一个临界资源,使用前应先lock,使用完后再unlock,如果使用不当,会有意外发生,但如果先unlock那么
mutex_lock_count 自减1,说明改互斥量将可以同时使用2次了。

条件变量操作函数:

/*初始化一个条件变量cond(布尔型),成功返回0,失败返回error错误标志*/

  1. int pthread_cond_init(pthread_cond_t *restrictcond,
  2. const pthread_condattr_t*restrict attr);

/*销毁一个条件变量cond,成功返回0,失败返回error错误标志*/

  1. int pthread_cond_destroy(pthread_cond_t*cond);

/*释放一个互斥量且等待(即阻塞当前线程)一个条件变量cond为真,后再lock*/

    1. <pre name="code" class="cpp"> int pthread_cond_timedwait(pthread_cond_t*restrict cond, pthread_mutex_t *restrict mutex,
    2. const struct timespec *restrictabstime);//等待条件变量cond是否为真,时限为abstime
    3. int pthread_cond_wait(pthread_cond_t*restrict cond,
    4. pthread_mutex_t *restrict mutex); //等待条件cond是否为真,时限为cond真为止</pre>
    5. <pre></pre>
    6. <p></p>
    7. <p>/*释放条件变量cond,唤醒先前已被阻塞的线程*/ </p>
    8. <p></p>
    9. <pre name="code" class="cpp"> intpthread_cond_broadcast(pthread_cond_t *cond);//唤醒所有因条件变量cond而阻塞的线程
    10. intpthread_cond_signal(pthread_cond_t *cond);//
      唤醒一个因条件变量cond而阻塞的线程</pre><pre name="code" class="cpp"><p&
      gt;<span style="font-size:10px;"></span></p></pre>
    11. <p></p>
    12. <p>编程实例:</p>
    13. <p>
      完成一个有趣的游戏(类似抢板凳):主线程中创建线程1,然后线程1再创建2个线程2,3,线程2,3分别对一个计数器操作counter(初值为0),
      线程1每使用一次加3,线程2每使用一次加5,如果加到被15整除,那么counter加8,看哪个线程先加到9999,并计算自己使用了多少次计算器。
      先到者胜利,并打印出相应信息。</p>
    14. <p>实现代码:</p>
    15. <p></p>
    16. <pre name="code" class="cpp">#include<pthread.h>
    17. #include<stdlib.h>
    18. #include<unistd.h>
    19. #include<stdio.h>
    20. #defineCOUNTER_MAX 9999
    21. static intCOUNTER;
    22. struct RESULT {
    23. pthread_t tid;
    24. int cnt1;
    25. int cnt2;
    26. };
    27. static structRESULT res;
    28. staticpthread_mutex_t   mux  = PTHREAD_MUTEX_INITIALIZER;
    29. staticpthread_cond_t    cond =PTHREAD_COND_INITIALIZER;
    30. static void *thread2(void *arg)
    31. {
    32. int ret;
    33. printf("enter thread2, tid =%lu\n",pthread_self());
    34. sleep(1);
    35. for (;;) {
    36. pthread_mutex_lock(&mux);
    37. if(COUNTER >= COUNTER_MAX) {
    38. ret = pthread_cond_signal(&cond); //唤醒一个因条件变量cond而阻塞的线程
    39. if (ret) printf("error in thread2\n");
    40. res.tid = pthread_self();
    41. pthread_mutex_unlock(&mux); //释放mux
    42. pthread_exit(0);
    43. }
    44. printf(".");
    45. fflush(stdout);
    46. COUNTER += 3;
    47. if(COUNTER%15 == 0 && COUNTER) {
    48. COUNTER += 8;
    49. usleep(50*res.cnt1);
    50. }
    51. res.cnt1++;
    52. pthread_mutex_unlock(&mux);
    53. usleep(COUNTER);
    54. }
    55. }
    56. static void *thread3(void *arg)
    57. {
    58. int ret;
    59. printf("enter thread3, tid =%lu\n",pthread_self());
    60. sleep(1);
    61. for (;;) {
    62. pthread_mutex_lock(&mux);
    63. if(COUNTER >= COUNTER_MAX) {
    64. ret = pthread_cond_signal(&cond); //唤醒一个因条件变量cond而阻塞的线程
    65. if (ret) printf("error in thread3\n");
    66. res.tid = pthread_self();
    67. pthread_mutex_unlock(&mux); //释放mux
    68. pthread_exit(0);
    69. }
    70. printf("o");
    71. fflush(stdout);
    72. COUNTER += 5;
    73. if(COUNTER%15 == 0 && COUNTER) {
    74. COUNTER += 8;
    75. usleep(50*res.cnt2);
    76. }
    77. res.cnt2++;
    78. pthread_mutex_unlock(&mux);
    79. usleep(COUNTER);
    80. }
    81. }
    82. static void *thread1(void *arg)
    83. {
    84. int ret;
    85. pthread_t tid2,tid3;
    86. printf("starting...\n");
    87. pthread_mutex_lock(&mux);
    88. ret =pthread_create(&tid2,NULL,thread2,NULL);
    89. if (ret) {
    90. printf("create thread1 error\n");
    91. }
    92. ret =pthread_create(&tid3,NULL,thread3,NULL);
    93. if (ret) {
    94. printf("create thread2 error\n");
    95. }
    96. pthread_cond_wait(&cond,&mux);   //释放mux,等待cond为真
    97. if (res.tid == tid2) {
    98. pthread_cancel(tid2);
    99. }
    100. else {
    101. pthread_cancel(tid3);
    102. }
    103. printf("\nget the winner:\n%s, tid= %lu,",(res.tid==tid2?"thread2":"thread3"),res.tid);
    104. printf("cnt1 = %d,cnt2 =%d\n",res.cnt1,res.cnt2);
    105. pthread_mutex_unlock(&mux);
    106. pthread_exit(0);
    107. }
    108. int main(void)
    109. {
    110. int ret;
    111. pthread_t tid1;
    112. ret =pthread_create(&tid1,NULL,thread1,NULL);
    113. if (ret) {
    114. printf("create thread1 error\n");
    115. }
    116. if (pthread_join(tid1,NULL)) { //等待thread1结束
    117. printf("error in thread1\n");
    118. }
    119. exit(0);
    120. }</pre>
    121. <p></p>
    122. <p>测试结果:</p>
    123. <p></p>
    124. <pre name="code" class="cpp">starting...
    125. enter thread3, tid= 3062217584
    126. enter thread2, tid= 3070610288
    127. o..o.o.o.o.o.o.o.o.oo..oo..o.o.o..oo..oo..o.o.o..oo..oo.o.o.o.o.o.o.o.o.o..oo..oo.o.o.o.o.o.o.o..oo.o..oo..o.o.o.o.o.o.o..o.oo.o.oo..oo.o.o.o.oo.o.o.o.o.o.o.o.o.o.o..o.oo.o.o.oo.o.o.o.o.o.o.o.o.o.o.o..oo..o.o..oo.o.o.o..o.o.o..o.o.o.o.oo.o.o.oo.o.o.o.o.o.o.o.o.o..o.oo..oo.o.oo.o..o.o.o.o..o.oo.o..o.o.o.o.o..o.oo.o.o.o.o.oo.o.o.oo.o.o.oo..oo.o.oo.o..o.o.o.o..o.oo..o.o.o.o..o.o.o.oo.o.oo.o.o.o.oo..oo.o.o.oo.o.o.oo..o.o.o.o..o.o.oo.o.o.o.oo..o.o..o.o.o.oo.o.o.oo.o..o.o..o.o.oo.o.o.o.oo.o..o.o.o..o.oo..o.o.o..o.o.o.o.oo.o.o.oo.o.o.o.o.oo.o.oo.o.o.o.oo.o.o.o.o.oo.o.o.oo.o..o.o..o.o.o.o.oo.o.o.oo.o.o.o.oo..o.o.o..o.oo.o.o.o.oo.o.o.o.oo.o.o.o.o.o.oo.o.o.oo.o.o.o.oo.o.o.o.oo.o.o.oo.o.o.o.oo.o.o.o.o.o.o.o.o.o..o.o.o.o.o.o..o.o.o.oo.o.o.oo.o.o.o.o.o.oo.o.o.oo.o.o.o.oo.o.o.o.oo.o.o.oo.o.o.o.o.o.o.o.o.o.o..o.oo.o..o.o.o.o.o..o.oo.o.o.o.oo.o.o.o.oo.o.o.o.o.oo.o.o.o.o.o.o.o.o.o..o.o.oo.o.o.oo.o.o.o.oo.o.o.o.oo.o.o.o.oo.o.o.o.oo.o.o.o.oo.o.o.oo.o..o.o.o..o.o.oo.o.o.o.o.oo.o.o.o.o.o.o.o.o..o.o.o.o.o.o.o..o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.oo.o.o.o.o.o.o.o.o.o.o.o.o..o.o.o.o.o..o.o.o.o.o.o.o.o.o.o.o.o.o.oo.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o..o.o.o.o.o.o.o..o.o..o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o..o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.oo.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o
    128. get the winner:
    129. thread2, tid =3070610288,cnt1 = 1046,cnt2 = 1072</pre>
    130. <p></p>
    131. <p style="margin-bottom:0cm" align="LEFT"><br>
    132. </p>
    133. <pre></pre>
    134. <pre></pre>
    135. <pre></pre>
    136. <pre></pre>
    137. <pre></pre>
    138. <pre></pre>
    139. <pre></pre>
    140. <pre></pre>
    141. 转载自:http://blog.csdn.net/yyplc====

posix thread 浅谈的更多相关文章

  1. 浅谈POSIX线程的私有数据

    当线程中的一个函数需要创建私有数据时,该私有数据在对函数的调用之间保持一致,数据能静态地分配在存储器中,当我们采用命名范围也许可以实现它使用在函数或是文件(静态),或是全局(EXTERN).但是当涉及 ...

  2. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  3. 浅谈Linux中的信号处理机制(二)

    首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...

  4. Android性能优化的浅谈

    一.概要: 本文主要以Android的渲染机制.UI优化.多线程的处理.缓存处理.电量优化以及代码规范等几方面来简述Android的性能优化 二.渲染机制的优化: 大多数用户感知到的卡顿等性能问题的最 ...

  5. 浅谈线程池(中):独立线程池的作用及IO线程池

    原文地址:http://blog.zhaojie.me/2009/07/thread-pool-2-dedicate-pool-and-io-pool.html 在上一篇文章中,我们简单讨论了线程池的 ...

  6. 浅谈线程池(上):线程池的作用及CLR线程池

    原文地址:http://blog.zhaojie.me/2009/07/thread-pool-1-the-goal-and-the-clr-thread-pool.html 线程池是一个重要的概念. ...

  7. 安装JDK后JRE与JVM联系浅谈

    转自安装JDK后JRE与JVM联系浅谈 安装JDK后JRE.JVM之间的关系是什么呢?那么我们要从安装JDK慢慢说起. 如果安装了JDK,会发同你的电脑有两套JRE: 一套位于 <JDK安装目录 ...

  8. 【转】浅谈Java中的hashcode方法(这个demo可以多看看)

    浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...

  9. 浅谈qmake之pro、pri、prf、prl文件

    浅谈qmake之pro.pri.prf.prl文件 转载自:http://blog.csdn.net/dbzhang800/article/details/6348432 尽管每次和cmake对比起来 ...

随机推荐

  1. LeetCode 337

    House Robber III The thief has found himself a new place for his thievery again. There is only one e ...

  2. 【转】 关于data factory的介绍——即如何快速生成大批量数据

    上次在我的博客中讲述了quest公司的spotlight系列软件,这次来扯淡一下quest公司的另一测试辅助软件 datafactory(数据工厂),顾名思义,数据工厂是生产数据的,主要应用领域是性能 ...

  3. Ajax异步操作集合啦(阿贾克斯)

    /* * Ajax的核心操作对象是xmlHttpRequest * 简化操作步骤:实例化一个xmlHttpRequest对象 ==> 发送请求 ==> 接受响应 ==> 执行回调 * ...

  4. 【Mongodb】---Scheme和Collections对应问题

    Mongodb通过mongoose来与数据进行操作.而mongoose是通过model来创建数据库中对应的collection mongoose.model('User', UserSchema); ...

  5. 【转载】Asp.net Mvc 入门视频教程

    专辑: http://www.youku.com/playlist_show/id_2416830.html 订阅: http://www.youku.com/playlist/rss/id/2416 ...

  6. 八、android jni 之C语言基础

    *含义 1.乘法 3*5 2.定义指针变量 int * p://定义了一个名字叫p的变量,能够存放int数据类型的地址 3.指针运算符, //如果p是一个已经定义好的指针变量则*p表示以p的内容为地址 ...

  7. sql server创建表相关

    1,设置主键的sql的三种方式 a.字段名 int primary key b.字段名 int constraint 主键名 primary key clustered(字段名) c.创建表是,后置一 ...

  8. WIN7实用的运行命令

    运行命令主要是DOS操作系统的运行方式.为方便用户的操作,微软公司将一些常用的命令,如DIR,CD等命令全部集成在系统里面:存放这些内部命令的文件是“Command”(文件后缀.com).它与IO.s ...

  9. 以OpenGL方式运行Unity

    Unity在Windows上默认以DirextX的方式运行,在MacOS和Linux上默认以OpenGl的方式运行, 如果希望在Windows上以OpenGL的方式运行可以在命令行中输入 -force ...

  10. (转)RabbitMQ消息队列的小伙伴: ProtoBuf(Google Protocol Buffer)

    什么是ProtoBuf? 一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化.它很适合做数据存储或 RPC 数据交换格式.可用于通讯协议.数据存储等领域的语言无关.平台无关.可扩 ...