c中的多线程详解
来源:互联网 发布:天庭淘宝店txt 编辑:程序博客网 时间:2024/06/05 15:13
什么是线程?
线程是进程里面的一个单独的序列流,因为线程包含一些进程的属性,所以线程也叫轻量级进程。
进程和线程有什么区别?
线程不是独立于其他类似进程,因此线程与其他线程共享其代码部分,数据部分和操作系统资源,如打开的文件和信号。但是像进程一样,线程也有自己的计数器(pc),寄存器集和堆栈空间。
为什么需要多线程?
线程是通过并行性改进应用程序的流行方式,例如在浏览器中多个选项卡可以对应不同线程,MS world使用多个线程,一个线程格式化文本,一个线程格式化输入。
线程的操作速度比进程快:
1.线程创建速度快
2.线程上下文切换快
3.线程可以轻松终止,简单快捷
4.线程之间通信速度快
我们可以在c中编写多线程程序吗?
与Java不同,语言标准不支持多线程。POSIX线程(或Pthreads)是针对线程的POSIX标准。gth编译器可以实现pthread。
来看一个简单的例子:
#include <pthread.h>#include <stdlib.h>#include <unistd.h> void *thread_function(void *arg) { int i; for ( i=0; i<20; i++) { printf("Thread says hi!\n"); sleep(1); } return NULL;}int main(void) { pthread_t mythread; if ( pthread_create( &mythread, NULL, thread_function, NULL) ) { printf("error creating thread."); abort(); } if ( pthread_join ( mythread, NULL ) ) { printf("error joining thread."); abort(); } exit(0);}这个程序最终会将
Thread says hi运行20次以后结束程序
程序编译与运行:
我们详细的来看看这个程序的细节:
上面是一个非常简单的线程的程序,虽然她没有什么实际有用的功能,但他可以帮助我们很好的理解线程的运行机制,下面我们一步步来看这个程序在干什么。mian()中声明了mythread,它的数据类型为pthread_t,这是定义在<pthread.h>中的一种数据类型,这里mythread相当于一个thread id(简称tid),就是线程id的意思,你也可以理解为一个线程句柄。
记住mythread只是一个线程句柄(tid)接下来我们就要用到pthread_creat()来创建一个真正活动的线程。pthread_creat()的返回值是0 OR 1意思是如果线程创建成功则返回0,创建失败返回1.这个函数中有四个参数:
第一个参数:&mythread 是指向 mythread 的指针。
第二个参数:当前为null,这个参数可以来定义线程的某些属性
第三个参数:当前创建的线程(下面叫做新线程)所要调用的函数,上面程序里是thread_function()这个函数,当该函数返回值时,新线程也终止。
第四个参数:这里是用来传参的,因为上面我们调用的thread_function()这个函数不需要参数,所以第四个参数设置为null。
我们还要清楚一点上面的程序我们实际是创建了两个线程,main()也是一个线程。我们可以这样理解,如果我们不用POSIX创建新线程,则我们以前写的程序都是单线程的。
你可能会想我们现在有了两个线程,但是它们究竟是怎么运行的呢?新线程创建以后主线程继续执行pthread_join()这个函数,当主线程到达这个函数时,由于新线程还没有运行完毕,所以主线程中断(咸党与休眠)等待新线程执行完毕后将新线程合并(你可以理解为释放掉或者清理掉)现在,程序就只有一个线程了。
我们来看一看pthread_join()这个函数的两个参数:第一个参数同样是一个指向mythread得指针,第二个参数和creat的第四个参数相似。当程序退出时,所有新线程已经使用 pthread_join() 合并了。这就是应该如何处理在程序中创建的每个新线程的过程。如果没有合并一个新线程,则它仍然对系统的最大线程数限制不利。这意味着如果未对线程做正确的清理,最终会导致 pthread_create() 调用失败。
下面我们来看一个同步漫游的例子可以帮助你更好的理解:
#include <pthread.h>#include <stdlib.h>#include <unistd.h>#include <stdio.h>int myglobal; void *thread_function(void *arg) { int i,j; for ( i=0; i<20; i++) { //myglobal += 1; j = myglobal; j=j+1; printf("."); fflush(stdout); sleep(1); myglobal=j; } return NULL;}int main(void) { pthread_t mythread; int i; if ( pthread_create( &mythread, NULL, thread_function, NULL) ) { printf("error creating thread."); abort(); } for ( i=0; i<20; i++) { myglobal=myglobal+1; printf("o"); fflush(stdout); sleep(1); } if ( pthread_join ( mythread, NULL ) ) { printf("error joining thread."); abort(); } printf("\nmyglobal equals %d\n",myglobal); exit(0);}
编译过程同上(略)
运行结果:
这个程序是双线程的,每个线程都给mythread加了20次1,但是结果为什么不是40呢,是不是有点惊讶,下面我们仔细的分析一下这个程序:
首先我们知道的是对于线程来说不像进程一样有子与父的区别,每一个进程都是平等的,处在同一层次的,对于上面这个程序,在这里两个线程几乎同时进行,产生上述结果差异的根本原因就在于thread_function()这个函数中我们把j的值赋值给myread是在sleep(1)后面,什么意思呢?就是新线程真正实现methread+1是发生在sleep(1)后面,这样当两个程序几乎同时进行时,新线程会将主线程的值覆盖这样就产生了21这个结果,你可以试着把程序中的注释去掉。稍加修改让新线程mythread+1发生在sleep之前,看看结果是什么?
阅读全文
1 0
- c中的多线程详解
- android中的多线程详解
- Java中的多线程详解
- 多线程中的ThreadLocal 详解
- C++builder 中的多线程
- Android开发中的多线程详解
- Android中的多线程编程详解
- Java中的多线程图文详解
- 详解Python中的多线程编程
- C/C++中的多线程入门
- C/C++中的多线程入门
- C/C++中的多线程入门
- C语言中的多线程编程
- C语言中的多线程编程
- 理解多线程中的ManualResetEvent(C#)
- C++/CLR 中的多线程使用方法
- C语言中的多线程编程
- 详解Java多线程开发中的数据同步
- Eigen与matlab的比较
- 词法分析器
- Problem A: 平面上的点——Point类 (I)
- solr中 schema.xml配置文件
- iOS Swift 复制一个 StoryBoard 中的面板
- c中的多线程详解
- Problem B: 平面上的点——Point类 (II)
- 子节点childNodes的兼容性问题
- 三道题讲并查集
- Problem C: 一元二次方程类
- zookeeper集群部署
- Problem D: 字符类的封装
- [Assembly] 程序的机器级表示(一)
- opencv 介绍 SIFT(Scale-Invariant Feature Transform)