用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. 关于onClick 提交数据问题

    我在添加 民工考勤表,用ajax 自动读取数据添加到相应模块之后 进行 OnClick="btnSubmit_Click" 保存,结果无法保存,之后我将光标锁定到某一个文本框内,就 ...

  2. 【JS对象、JSON字符串】之间的相互转换

    在Firefox,chrome,opera,safari,ie9,ie8等浏览器直接可以用JSON对象的stringify()和parse()方法. 1.JSON.stringify(obj)将JS对 ...

  3. Part 67 to 70 Talking about method parameters in C#

    Part 67 Optional parameters in c# Part 68  Making method parameters optional using method overloadin ...

  4. yarn.resourcemanager.ha.id设置

    resourcemanager启动报错,其中一个启动成功,另一个启动报8088端口被成功启动的rm占用 2016-11-18 17:08:49,478 INFO org.apache.zookeepe ...

  5. 利用 NUget包 EPPlus 实现数据导出到Excel(适用于MVC)

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvoAAABpCAIAAADEEBBGAAAJdElEQVR4nO3cy2ob5wLA8TxKnqTrrr

  6. UI1_UITouch

    // // ViewController.m // UI1_UITouch // // Created by zhangxueming on 15/7/9. // Copyright (c) 2015 ...

  7. (转)Linux vmstat命令实战详解

    vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况.这个命令是我查看Linux/Unix最 ...

  8. (转)RabbitMQ消息队列(一): Detailed Introduction 详细介绍

    1. 历史 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有 ...

  9. Facebook抛弃了HTML5,微信却捧火了它

    苹果普及了HTML5技术,Facebook押注HTML5上,却受到不小的打击,导致在后来一段时间里,唱衰HTML5的言论成为媒体的一种幸灾乐祸的态度,人人避而不谈.微信通过公众号的形式,以游戏.营销重 ...

  10. 6款基于SVG的HTML5CSS3应用和动画

    1.CSS3/SVG质感背景小图标 镂空效果图标按钮 今天我们来分享一款用CSS3和SVG实现的质感背景小图标,鼠标滑过图标时出现镂空的效果,并且有质感背景的描边,效果非常不错. 在线演示 源码下载 ...