前面章节中介绍了进程。从这一章开始介绍线程。进程和线程的差别是什么呢:

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。 
1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 
2) 线程的划分尺度小于进程,使得多线程程序的并发性高。 
3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 
4) 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 
5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。 
4.优缺点 
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。

用一个比喻来形容进程和线程。一个工厂里面是由多个车间组成。进程就好比工厂的车间。它代表CPU所能处理的单个任务。但是一个车间里可以有多个工人,他们协同完成车间里面的任务。这些工人就可以看做是线程。因此一个进程里面可以包含多个线程。

车间里面的空间都是工人们共享的,这就代表一个进程的内存空间是共享的。每个线程都可以使用这些共享内存。

但是有可能车间里的某个房间空间有限,只能容纳一个人,比如厕所,里面有人的时候其他人就不能进去,这就代表线程使用某些共享内存的时候,其他线程必须等它结束才能使用这块内存。

为了防止其他人进入房间,就是在房间上加一把锁,先到的人锁上门,后到的人看到上锁,就在门口排队。等锁打开再进去,这就是互斥锁,防止多个线程同时读写某一个块内存区域。

还有些房间可以容纳n个人,如果人数大于n,多出来的人只能在外面等着,就好比某些内存只能给固定数目的线程使用。解决的办法就是在门口挂n把钥匙,进入的人取一把钥匙,出来的时候再把钥匙挂回原处。后到的人发现钥匙架空了就知道必须在门口排队等待。这种做法就叫做信号量。用来保证多个线程不会互相冲突。

下面来看下线程的具体用法:

就像每个进程有一个进程ID一样,每个线程也有一个线程ID。和进程ID在整个系统中是唯一的不同,线程ID只有在它所属的进程上下文中才有意义

线程可以通过pthread_self函数来获得自身的线程ID

#include <pthread.h>

pthread_t pthread_self(void);

当一个程序启动时,就有一个进程被操作系统创建,与此同时一个线程也立刻运行,这个线程就是程序的主线程。如果需要再创建子线程,那么创建的线程就是这个主线程的子线程。主线程把新的作业放到一个工作队列中,主线程不允许每个线程任意处理从队列顶端取出的作业,而是由主线程控制作业的分配。

线程创建:

#include <pthread.h>

pthread_t pthread_create(pthread_t
*restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *),void
*restrict arg);

start_rtn: 新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg。如果需要向start_rtn函数传递的参数有一个以上,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为art参数传入

来看一个实际的代码:

#include <stdio.h>

#include <stdlib.h>

#include "func.h"

#include <pthread.h>

#include <unistd.h>

#include <windows.h>

void printids(const char *s){

pid_t pid;

pthread_t tid;

pid=getpid();

tid=pthread_self();

printf("%s pid %lu tid %lu (0x%lx)\n",s,(unsigned
long)pid,(unsigned long)tid,(unsigned long)tid);

}

void *thr_fn(void *arg){

printids("new thread:");

return((void *)0);

}

pthread_t ntid;

int main()

{

int err;

err=pthread_create(&ntid,NULL,thr_fn,NULL);

printids("main thread:");

Sleep(1);

return 0;

}

运行如下:可以看到两个线程的PID都是一样的,不同的是tid

那么线程什么时候退出呢,单个线程有3种方式退出,因此可以在不终止整个进程的情况下,停止它的控制流

1 线程可以简单地从启动例程中返回,返回值是线程的退出码

2 线程可以被同一进程的其他线程取消

3 线程调用pthread_exit

来看下进程中的其他线程如何来取消线程,这就需要用到pthread_join(pthread_t thread, void **rval_ptr)

运行后调用线程一直阻塞,直到指定的线程调用pthread_exit, 退出或者返回

#include <stdio.h>

#include <stdlib.h>

#include "func.h"

#include <pthread.h>

#include <unistd.h>

#include <windows.h>

void *thr_fn2(void *arg){

printf("thread2 exiting\n");

return((void *)2);

}

void *thr_fn1(void *arg){

printf("thread1 returning\n");

return((void *)1);

}

int main()

{

pthread_t tid1,tid2;

void *tret;

pthread_create(&tid1,NULL,thr_fn1,NULL);

pthread_create(&tid2,NULL,thr_fn2,NULL);

pthread_join(tid1,&tret);

printf("thread1 exit code %ld\n",(long)tret);

pthread_join(tid2,&tret);

printf("thread2 exit code %ld\n",(long)tret);

return 0;

}

运行结果:

linux c编程:线程创建的更多相关文章

  1. Linux多线程编程——线程的创建与退出

    POSIX线程标准:该标准定义了创建和操纵线程的一整套API.在类Unix操作系统(Unix.Linux.Mac OS X等)中,都使用Pthreads作为操作系统的线程.Windows操作系统也有其 ...

  2. Linux系统编程——线程私有数据

    在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...

  3. linux系统编程--线程

    安装线程man page,命令:sudo apt-get install manpages-posix-dev 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本 ...

  4. Unix 环境高级编程---线程创建、同步、

    一下代码主要实现了linux下线程创建的基本方法,这些都是使用默认属性的.以后有机会再探讨自定义属性的情况.主要是为了练习三种基本的线程同步方法:互斥.读写锁以及条件变量. #include < ...

  5. Linux 多线程编程--线程退出

    今天分析项目中进程中虚存一直增长问题,运行10个小时虚存涨到121G ,RSS占用为16G 非常恐怖. Valgrind测试无内存泄漏. 内存32G 64bit系统信息如下: Linux线程使用方式是 ...

  6. Linux多任务编程——线程

    线程基础 △ 由于进程的地址空间是私有的,因此在进行上下文切换时,系统开销比较大 △ 在同一个进程中创建的线程共享该进程的地址空间 △ 通常线程值得是共享相同地址空间的多个任务 △ 每个线程的私有这些 ...

  7. linux系统编程--线程同步

    同步概念 所谓同步,即同时起步,协调一致.不同的对象,对“同步”的理解方式略有不同. 如,设备同步,是指在两个设备之间规定一个共同的时间参考: 数据库同步,是指让两个或多个数据库内容保持一致,或者按需 ...

  8. LInux多线程编程----线程特定数据的处理函数

    1.pthread_key_t和pthread_key_create() 线程中特有的线程存储, Thread Specific Data .线程存储有什么用了?他是什么意思了?大家都知道,在多线程程 ...

  9. Linux系统编程 —线程属性

    在之前的章节中,我们在调用pthread_create函数创建线程时,第二个参数(即线程属性)都是设为NULL,即使用默认属性.一般情况下,使用默认属性已经可以解决我们开发过程中的大多数问题. 但是, ...

  10. Linux系统编程 —线程同步概念

    同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ...

随机推荐

  1. WCF 404.3 MIME 映射错误

    WCF部署在IIS下,报错如下: HTTP 错误 404.3 - Not Found由于扩展配置问题而无法提供您请求的页面.如果该页面是脚本,请添加处理程序.如果应下载文件,请添加 MIME 映射. ...

  2. ListView:聊天界面

    一.最终成型图 二.主界面xml布局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...

  3. vue相关知识点

    1.el-date-picker输入的时间范围需要两点 A.禁用键盘输入 :editable=false,否则虽然禁用,但是输入框还能输入 B.指定时间范围::picker-options=" ...

  4. react-native 详解

    1.获取主屏幕尺寸 // 导入类库 var Dimensions = require('Dimensions'); // 样式 const styles = StyleSheet.create({ c ...

  5. Unix环境部署

    http://www.cnblogs.com/chuyuhuashi/p/4423699.html 分布式javahttp://www.cnblogs.com/tangyanbo/p/4499485. ...

  6. 【Excle数据透视表】如何在数据透视表中使用合并单元格标志

    先有数据透视表如下: 现在看着这个格式不舒服,我们希望调整成如下这种样式 步骤 单击数据透视表任意单元格→右键→数据透视表选项→布局和格式→合并且居中排列带标签的单元格 注意:如果数据透视表报表布局不 ...

  7. Maven 缺省内置变量

    1.${project.build.directory} 构建目录,缺省为target 2.${project.build.outputDirectory} 构建过程输出目录,缺省为target/cl ...

  8. Javascript 客户端实时显示服务器时间

    <!doctype html> <html lang="zh-cn"> <head> <meta charset="utf-8& ...

  9. AIX 安装标准

    文件夹 一.网卡需求 二.光纤卡需求 三.磁盘需求 四.主机文件系统需求 五.主机名命名规范 六.安装设置规范 七.參数改动规范 八.时钟同步设置 九.rootvg做镜像 十.AIX系统安全加固 一. ...

  10. CSS遮罩层,全兼容

    <script type="text/javascript"> $(function(){ $('#divLocker').css({ "position&q ...