linux c编程:线程创建
前面章节中介绍了进程。从这一章开始介绍线程。进程和线程的差别是什么呢:
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是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编程:线程创建的更多相关文章
- Linux多线程编程——线程的创建与退出
POSIX线程标准:该标准定义了创建和操纵线程的一整套API.在类Unix操作系统(Unix.Linux.Mac OS X等)中,都使用Pthreads作为操作系统的线程.Windows操作系统也有其 ...
- Linux系统编程——线程私有数据
在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...
- linux系统编程--线程
安装线程man page,命令:sudo apt-get install manpages-posix-dev 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本 ...
- Unix 环境高级编程---线程创建、同步、
一下代码主要实现了linux下线程创建的基本方法,这些都是使用默认属性的.以后有机会再探讨自定义属性的情况.主要是为了练习三种基本的线程同步方法:互斥.读写锁以及条件变量. #include < ...
- Linux 多线程编程--线程退出
今天分析项目中进程中虚存一直增长问题,运行10个小时虚存涨到121G ,RSS占用为16G 非常恐怖. Valgrind测试无内存泄漏. 内存32G 64bit系统信息如下: Linux线程使用方式是 ...
- Linux多任务编程——线程
线程基础 △ 由于进程的地址空间是私有的,因此在进行上下文切换时,系统开销比较大 △ 在同一个进程中创建的线程共享该进程的地址空间 △ 通常线程值得是共享相同地址空间的多个任务 △ 每个线程的私有这些 ...
- linux系统编程--线程同步
同步概念 所谓同步,即同时起步,协调一致.不同的对象,对“同步”的理解方式略有不同. 如,设备同步,是指在两个设备之间规定一个共同的时间参考: 数据库同步,是指让两个或多个数据库内容保持一致,或者按需 ...
- LInux多线程编程----线程特定数据的处理函数
1.pthread_key_t和pthread_key_create() 线程中特有的线程存储, Thread Specific Data .线程存储有什么用了?他是什么意思了?大家都知道,在多线程程 ...
- Linux系统编程 —线程属性
在之前的章节中,我们在调用pthread_create函数创建线程时,第二个参数(即线程属性)都是设为NULL,即使用默认属性.一般情况下,使用默认属性已经可以解决我们开发过程中的大多数问题. 但是, ...
- Linux系统编程 —线程同步概念
同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ...
随机推荐
- MySQL的左外连接
代码: select t1.descid, IFNULL(t2.cnt,) as countnew, t1.description from uosdesc t1 left outer join t2 ...
- mysql binlog 使用
用于数据恢复的binlog 前提条件 1.定时mysqldumps全备数据库 2.开启binlog增量备份 情景:手滑误操作删表操作 立刻 mysql>flush logs; #开启一个新的b ...
- JAVA Eclipse 启动 Eclipse 弹出“Failed to load the JNI shared library jvm_dll”怎么办
原因1:给定目录下jvm.dll不存在. 对策:(1)重新安装jre或者jdk并配置好环境变量.(2)copy一个jvm.dll放在该目录下. 原因2:eclipse的版本与jre或者jdk版本不一致 ...
- PS如何拉倒影效果
1 复制图形(一般是文字)并垂直翻转得到倒影的初步样子(最好倾斜一下,看起来逼真一些)就像下面的迅雷的样子.记住要栅格化文字. 2 用魔棒工具抠除原来的颜色,只剩下空的选区. 3 拉渐变
- URL相对路径和URL绝对路径
经常在页面中引用图片,html页面等,自己常常弄错相对路径和绝对路径,今天写下此文总结一下. 直接举例说明吧. 在 D:\例子\html下有这么几个文件和文件夹 1.若引用的资源和本身在 ...
- MQTT--linux安装部署(CentOS)
OS环境:CentOS6.5 1.安装依赖 yum -y install gcc gcc-c++ openssl-devel c-ares-devel libuuid-devel wget cmake ...
- 读书报告之《改动代码的艺术》 (I)
<改动代码的艺术>,英文名<Working Effectively with Legacy Code>,中文翻译的文笔上绝对谈不上"艺术"二字.愧对艺术二字 ...
- 数据结构之shell排序
#SIZE 10 //直接插入排序 void insert_sort(){ int i,j; int array[SIZE+1]; ...
- threw load() exception java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet(maven项目git后)
maven项目git全新项目后启动服务出现的, 错误原因: 进入到tomcat的部署路径.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpw ...
- uboot和内核分区的改动
随着内核的更新,内核越来越大,uboot给nand的kernel分区默认是2M的 device nand0 <nandflash0>, # parts = 4 #: name ...