用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. A的href和onclick

    我们在制作网页的时候用得最多的就是 A 标签 超连接 但有时候需要在 A 里同时用到 href 和 onclick属性 下面我们先来分析一下 ,在不同的浏览器下有不同的效果 1 顺序 ie 6 : h ...

  2. 让UIScrollView、UITableView的滚动条一直显示

    先用xcode5.1.1或更低版本创建一个Category,如图: 然后拷贝以下代码到刚创建的UIImageView+ForScrollView.m文件中: - (void) setAlpha:(fl ...

  3. 根据不同的分辨率选择不同的css文件

    <SCRIPT language=javascript> <!-- Begin if (screen.width == 640) { document.write('<link ...

  4. wamp图标黄色的另一种可能原因

    学习php用的是wamp即windows+apache+mysql+php,但是当启动的时候,图标为黄色(正常应为绿色),开始以为是端口的问题,但是将端口改掉依旧如此,后来发现是机器装的sqlserv ...

  5. [Fiddler]Unable to Generate Certificate

    I'm using Fiddler2 (or trying) to capture SSL traffic for a windows desktop gadget hitting an https ...

  6. ASP.NET发布WebService

    1. 创建一个空的Web应用程序 2. 再添加一个Web服务 3. 在所创建Web服务内,编写一算法 4. 写完可直接运行查看结果 5. 项目->右键,发布此WebService 6.  发布至 ...

  7. c#高级编程第七版 学习笔记 第一章 .NET体系结构

    第一章      .NET体系结构 本章内容: 编译和运行面向.NET的代码 Microsoft中间语言(Microsoft Intermediate Language,MSIL或简称IL)的优点 值 ...

  8. (转)集成架构:对比 Web API 与面向服务的架构和企业应用程序集成

    摘要:总体上讲,SOA 和 Web API 似乎解决的是同一个问题:以实时的.可重用的方式公开业务功能.本教程将分析这些举措有何不同,以及如何将它们融入到一个不断演变的集成架构中.文中还将讨论 API ...

  9. node笔记——gulp修改静态文件的名字

    cmd小技巧: 1.换到下级或同等级目录 D: 2.换到上级目录 cd.. node 包管理器小技巧[以gulp为例] npm install --save-dev gulp gulp-concat ...

  10. SQL 建表与查询 HTML计算时间差

    create database xue1 go --创建数据库 use xue1 go --引用数据库 create table xinxi ( code int, name ), xuehao ), ...