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来查询 ...
随机推荐
- 【POJ 2417】 Discrete Logging
[题目链接] http://poj.org/problem?id=2417 [算法] Baby-Step,Giant-Step算法 [代码] #include <algorithm> #i ...
- 南海区行政审批管理系统接口规范v0.3(规划)4.2.【queryExpireList】当天到期业务查询
加密前:{"time":"1510053168455","username":"GH_DATA_EXCHANGE",&q ...
- 08.HttpUrlconnection方式调用
package com.rl.client; import java.io.BufferedInputStream; import java.io.BufferedReader; import jav ...
- [JavaEE] Apache Maven 入门篇(下)
http://www.oracle.com/technetwork/cn/community/java/apache-maven-getting-started-2-405568-zhs.html 作 ...
- B - Expression
Problem description Petya studies in a school and he adores Maths. His class has been studying arith ...
- .net中的母版页中使用FindControl的使用
前几天,遇到一个字段比较多的用户填写的页面(数据库表中就将近100个字段),怎么讲这些input的标签的值,保存数据库了?(使用的是母版页下面的aspx,不包括前段获取input的值,传给后台) 作为 ...
- deepin下jdk和tomcat的安装教程
在deepin上安装java是真的心累啊,照着网上的教程弄,结果一团糟.好不容易折腾成功了,记录下来. 1.下载jdk 首先我们要知道,用sudo 类似命令下载的jdk,是open的jdk,是开源的, ...
- 给<hr/>添加样式
点线式 破折线式 直线式 双线式 脊线式 槽线式 内嵌效果的 突起效果的 border-top:10px 设置水平线的大小 <hr style=" border-top:5px dot ...
- 一个不错的学习android的网站
http://androiddoc.qiniudn.com/guide/topics/ui/overview.html,最近想学下android的开发,找了一下网上的资料,中文的说的觉得太概括,看不太 ...
- redis RDB快照和AOF日志持久化配置
Redis持久化配置 Redis的持久化有2种方式 1快照 2是日志 Rdb快照的配置选项: save 900 1 // 900内,有1条写入,则产生快照 save 300 1000 ...