用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. 各种"居中"

    先看效果 代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> < ...

  2. jQuery过滤选择器:not()方法使用介绍

    在jQuery的早期版本中,:not()筛选器只支持简单的选择器,说明我们传入到:not这个filter中的selector可以任意复杂,比如:not(div a) and :not(div,a) & ...

  3. 转: Android入门及效率开发

    评注: android第三方开源框架介绍不错 转:https://segmentfault.com/a/1190000004495351 入门 Android官方培训课程中文版:http://huka ...

  4. How To Install Development Tools In Linux

      In this brief tutorial, we will be discussing how to install development tools in popular Linux di ...

  5. 手机app(功能)测试重点

    在手机客户端进行查看的测试重点:1.“点击加载更多”的分页处理技术,是否有重复的数据,数据显示是否完整,到达最后一页后是否还有数据进行显示2.数据的排序方式2.界面跳转是否正确3.出现异常情况是否有提 ...

  6. 【CSS3】---为边框应用图片 border-image

    为边框应用图片 border-image 顾名思义就是为边框应用背景图片,它和我们常用的background属性比较相似.例如: background:url(xx.jpg) 10px 20px no ...

  7. 跟我学习dubbo-简介(1)

    1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...

  8. 正确使用Android性能分析工具——TraceView

    http://blog.jobbole.com/78995/     首页 最新文章 IT 职场 前端 后端 移动端 数据库 运维 其他技术 - 导航条 - 首页 最新文章 IT 职场 前端 - Ja ...

  9. lua技巧分享之保护执行

    我们在c#/c++里为了防止调用出现异常的时候程序可以正常的执行,经常使用try{}catch{}的结构, 那么,语言简单的lua是怎么做到的呢?答案就在pcall 先简单的介绍一下这个函数: --尝 ...

  10. ASP.NET 使用 System.Web.Script.Serialization 解析 JSON (转)

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programming Langu ...