POSIX 线程编程(二)线程建立与终止
创建与终止线程
线程的管理常用的API有:
pthread_create(thread,attr,start_routine,arg)
pthread_exit(status)
pthread_cancel(thread)
pthread_attr_init(attr)
pthread_attr_destroy(attr)
创建线程:
一个main程序包含一个默认的主线程,这个主线程在程序开始运行的时候由系统创建。除此之外的所有其他线程必须由程序员显式的创建。
pthread_create 创建一个可执行的线程。每次调用创建一个线程,同时,你可以在任何位置调用该函数。
pthread_create 参数:
- thread:唯一标示一个新线程的用户不可见的标识符,由pthread_create产生
- attr:一个线程的不可见的属性对象,可以用来设置新建线程的属性。可以传进一个线程属性对象,类型为pthread_attr_t;或者传NULL来使用默认值。
- start_routine: 新线程创建好之后由新线程立即执行的子程序
- arg:传给 start_routine的一个参数。它必须为void类型的指针,当然没有参数或者使用默认可以传NULL。如果想传进多个参数,可以它们封装进一个结构体。
一个进程可以创建的线程数量的最大值在不同的系统内有不同的实现。
在Linux查询和设置你的系统的线程数量限制方法如下:
bash / ksh / sh tcsh / csh $ ulimit -a
core file size (blocks, -c) 16
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 255956
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) unlimited
cpu time (seconds, -t) unlimited
max user processes (-u) 1024
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited $ ulimit -Hu
7168 $ ulimit -u 7168 $ ulimit -a
core file size (blocks, -c) 16
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 255956
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) unlimited
cpu time (seconds, -t) unlimited
max user processes (-u) 7168
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited% limit
cputime unlimited
filesize unlimited
datasize unlimited
stacksize unlimited
coredumpsize 16 kbytes
memoryuse unlimited
vmemoryuse unlimited
descriptors 1024
memorylocked 64 kbytes
maxproc 1024 % limit maxproc unlimited % limit
cputime unlimited
filesize unlimited
datasize unlimited
stacksize unlimited
coredumpsize 16 kbytes
memoryuse unlimited
vmemoryuse unlimited
descriptors 1024
memorylocked 64 kbytes
maxproc 7168一旦建立,线程之间是并行的,同时可以在线程内创建新的线程。线程之间没有继承或者依赖关系。
线程属性
默认情况下,一个线程创建之后包含一些默认属性。其中一些可以由传递进去的线程属性对象改变。
pthread_attr_init 和 pthread_attr_destroy 用来初始化和销毁一个线程属性对象
还有一些其他API可以用来查询或者设置线程属性对象中的特定的属性。线程的属性包括:
- 分离或可结合状态
- 调度继承
- 调度策略
- 调度参数
- 调度竞争范围
- 栈尺寸
- 栈地址
- 栈保护区大小
终止线程 pthread_exit():
线程在以下几种情况下会终止:
- 线程从其start_routine正常返回,其工作全部完成
- 线程调用了pthread_exit(),无论其工作是否完成
- 线程被其他线程通过调用pthread_cancel()取消
- 线程所在的进程调用了exec() 或者 exit()
- main()函数结束
pthread_exit()允许程序员指定一个可选的终止状态参数。这个可选的参数通常将返回线程“加入”终止线程。
- pthread_exit()不会关闭文件,任何在线程内打开的文件在线程通过调用pthread_exit()终止后仍继续保持打开状态。
线程的创建和终止示例代码
- 在这个简单的例子中将通过调用prhtread_ctreate()建立5个线程,每个线程输出“Hello World!”,然后调用pthread_exit()终止。这里是结果
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5 void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
} int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-);
}
} /* Last thing that main() should do */
pthread_exit(NULL);
}
向线程传递参数
pthread_create()允许传递一个参数到线程启动时调用的函数即所谓的start_routine。在需要传多个参数的时候,可以通过创建一个封装很多参数的结构体,然后将指向该结构体的指针传给 pthread_create()就可以了。
所有的参数必须以指针形式传递,同时转为类型为void。
线程传递参数的示例代码:这里是结果
/******************************************************************************
* FILE: hello_arg1.c
* DESCRIPTION:
* A "hello world" Pthreads program which demonstrates one safe way
* to pass arguments to threads during thread creation.
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 8 char *messages[NUM_THREADS]; void *PrintHello(void *threadid)
{
int *id_ptr, taskid; sleep();
id_ptr = (int *) threadid;
taskid = *id_ptr;
printf("Thread %d: %s\n", taskid, messages[taskid]);
pthread_exit(NULL);
} int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int *taskids[NUM_THREADS];
int rc, t; messages[] = "English: Hello World!";
messages[] = "French: Bonjour, le monde!";
messages[] = "Spanish: Hola al mundo";
messages[] = "Klingon: Nuq neH!";
messages[] = "German: Guten Tag, Welt!";
messages[] = "Russian: Zdravstvytye, mir!";
messages[] = "Japan: Sekai e konnichiwa!";
messages[] = "Latin: Orbis, te saluto!"; for(t=;t<NUM_THREADS;t++) {
taskids[t] = (int *) malloc(sizeof(int));
*taskids[t] = t;
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskids[t]);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-);
}
} pthread_exit(NULL);
}
传递多个参数的例子,请看这里
Joining and Detaching 线程
pthread_join(threadid,status)
pthread_detach(threadid)
pthread_attr_setdetachstate(attr,detachstate)
pthread_atr_getdetachstate(attr,detachstate)
Joining:
"Joining"是线程间同步的一种方式。
pthread_join()会阻塞调用的线程直至制定的threadid线程终止
如果在指定的目标线程中调用pthread_exit(),程序员可以获得目标线程的终止返回状态。
线程一个创建,其中的一个属性就被制定为joinable或者detached。而且只有joinable的线程才可以使用这种同步方式。
显式的创建一个线程为joinable或者detached,可以在pthread_create()中使用属性参数,步骤如下: 1) 声明一个线程属性变量,类型为pthread_attr_t 2) 使用pthread_attr_init()初始化属性变量 3) 使用pthread_attr_setdetachstate()设置属性分离状态 4) 程序结束时,使用pthread_attr_destroy()释放属性对象使用的资源
还有两种同步方法,互斥锁和条件变量,将在以后的blog中讨论
Detaching
pthread_detach()可以显式的detach一个线程即便它创建的时候是joinable。
没有相反的API
Pthread Joining示例代码如下:这里是结果
/*****************************************************************************
* FILE: join.c
* DESCRIPTION:
* This example demonstrates how to "wait" for thread completions by using
* the Pthread join routine. Threads are explicitly created in a joinable
* state for portability reasons. Use of the pthread_exit status argument is
* also shown. Compare to detached.c
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 4 void *BusyWork(void *t)
{
int i;
long tid;
double result=0.0;
tid = (long)t;
printf("Thread %ld starting...\n",tid);
for (i=; i<; i++)
{
result = result + sin(i) * tan(i);
}
printf("Thread %ld done. Result = %e\n",tid, result);
pthread_exit((void*) t);
} int main (int argc, char *argv[])
{
pthread_t thread[NUM_THREADS];
pthread_attr_t attr;
int rc;
long t;
void *status; /* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); for(t=; t<NUM_THREADS; t++) {
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-);
}
} /* Free attribute and wait for the other threads */
pthread_attr_destroy(&attr);
for(t=; t<NUM_THREADS; t++) {
rc = pthread_join(thread[t], &status);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-);
}
printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status);
} printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
POSIX 线程编程(二)线程建立与终止的更多相关文章
- day31_8.12并发编程二线程
一.进程间的通信 在进程中,可以通过Queue队列进行通信,队列有两个特点: 1.先进先出.(先来的数据先被取出) 2.管道式存取.(数据取出一次后就不会在有了) 在python中有以下方法来操作数据 ...
- linux线程篇 (二) 线程的基本操作
线程 进程 标识符 pthread_t pid_t 获取ID pthread_self() getpid() 创建 pthread_create() fork 销毁 pthread_exit() ...
- 异步线程编程,线程池,线程组,后面涉及ThreadLocal在理解
join模拟订单 package com.future.demo.future; /** * * * @author Administrator * */ public class NormalThr ...
- linux c编程:线程互斥二 线程死锁
死锁就是不同的程序在运行时因为某种原因发生了阻塞,进而导致程序不能正常运行.阻塞程序的原因通常都是由于程序没有正确使用临界资源. 我们举个日常生活中的例子来比喻死锁.我们把马路上行驶的汽车比作运行着的 ...
- Python 之并发编程之线程上
一.线程概念 进程是资源分配的最小单位 线程是计算机中调度的最小单位 多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都 ...
- Posix线程编程指南(4) 线程终止
线程终止方式 一般来说,Posix的线程终止有两种情况:正常终止和非正常终止.线程主动调用pthread_exit()或者从线程函数中return都将使线程正常退出,这是可预见的退出方式:非正常终止是 ...
- Posix线程编程指南
Posix线程编程指南 Posix线程编程指南... 1 一线程创建与取消... 2 线程创建... 2 1.线程与进程... 2 2. 创建线程... 2 3. 线程创建属性... 2 4. 创建的 ...
- Posix线程编程指南(1)
这是一个关于Posix线程编程的专栏.作者在阐明概念的基础上,将向您详细讲述Posix线程库API.本文是第一篇将向您讲述线程的创建与取消. 一.线程创建 1.1 线程与进程相对进程而言,线程是一 ...
- Unix环境高级编程(十二)线程控制
本章介绍了一个进程中多个线程之间如何保持数据的似有性及进程的系统调用如何与线程进行交互. 1.线程限制: Single Unix定义了一线线程操作的限制,和其他的限制一样,可以通过sysconf来查询 ...
随机推荐
- 实战Java内存泄漏问题分析 -- hazelcast2.0.3使用时内存泄漏 -- 2
hazelcast 提供了3中方法调用startCleanup: 第一种是在ConcuurentMapManager的构造函数中,通过调用node的executorManager中的Scheduled ...
- C++数组类模板
* 作为数组类模板,肯定没有vector做得好,可是普通的数组有1个优点就是能直接操作内存.vector在这方面就不是非常方便了. 网上尽管也有数组类模板.多维的设计基本上都不是非常好.我这个类模板多 ...
- luogu4012 深海机器人问题 网络流
关键词:最小费用最大流 题目大意:海底是个网格,每个网格边有一定价值的海底化石.每个路线可经过无限个机器人,但上面的化石只能采一次.机器人可沿网格边向东或向北移动.给定机器人起点和终点位置及所能容纳的 ...
- 10.2 Hibernate持久层
点击项目右键->MyEclipse->Add Hibernate Capabilities 打开MyEclipse Hibernate Perspective(MyEclipse Hibe ...
- php获取uniqid
md5(uniqid(microtime(true),true))
- linux系统下块设备驱动程序
顾名思义,块设备驱动程序就是支持以块的方式进行读写的设备.块设备和字符设备最大的区别在于读写数据的基本单元不同.块设备读写数据的基本单元为块,例 如磁盘通常为一个sector,而字符设备的基本单元为字 ...
- css3 animate基本属性
Css3animate属性 属性 描述 Css Animation 所有动画属性的简写属性,除了animation-play-state属性 Animation:name duration timin ...
- Java 系列之spring学习--注解(三)
一.注解 使用注解之前要开启自动扫描功能 <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...
- Gitlab 灾备措施
Gitlab创建备份 使用Gitlab一键安装包安装Gitlab非常简单,同样的备份恢复与迁移也非常简单.使用一条命令即可创建完整的Gitlab备份: gitlab-rake gitlab:ba ...
- hdu1853 Cyclic Tour 完美匹配 验证模版
题意: 给出n个城市和m条路,每个城市只能经过一次,想要旅游所有的城市,求需要的最小花费(路径的长度). 分析: 做题之前,首先要知道什么是完美匹配.不然题目做了却不知道为什么可以用这个方法来做.完美 ...