线程创建

在传统Unix进程模型中,每个进程只有一个控制线程。在POSIX线程(pthread)的情况下,程序开始运行时,它也是以单进程中的单个控制线程启动的。在创建多个控制线程以前,程序的行为与传统的进程并没有什么区别。新增的线程可以通过调用pthread_create函数创建。

#include <pthread.h>

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

说明:当pthread_create成功返回时,新创建线程的线程ID会被设置成tidp指向的内存单元。attr参数用于定制各种不同的线程属性,目前设置为NULL,创建一个具有默认属性的线程。
新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg。如果需要想start_rtn函数传递的参数有一个以上,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

例子

创建一个线程,打印进程ID、新线程的线程ID以及初始线程的ID。

//gcc threadid.c -o a.out -pthread
//pthread是linux下的线程库,用了多线程就要链接这个库,这时候要在编译选项上增加-pthread
#include "apue.h"
#include <pthread.h>
#include <apueerror.h>

pthread_t ntid;

void
printids(const char *s)
{
	//声明进程id
	pid_t		pid;
	//声明线程id
	pthread_t	tid;
	//获取进程id
	pid = getpid();
	//用pthread_self()获取自己线程id
	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)
{
	//调用上面的打印id函数
	printids("new thread: ");
	return((void *)0);
}

int
main(void)
{
	int		err;

	//创建线程,主线程把新线程ID存放在ntid中,新线程去执行thr_fn函数
	err = pthread_create(&ntid, NULL, thr_fn, NULL);
	if (err != 0)
		err_exit(err, "can't create thread");
	printids("main thread:");
	sleep(1);
	exit(0);
}

编译: gcc threadid.c -o a.out -pthread
note:pthread是linux下的线程库,用了多线程就要链接这个库,这时候要在编译选项上增加-pthread

main thread: pid 1518 tid 140627397551936 (0x7fe65e13a740)
new thread:  pid 1518 tid 140627389191936 (0x7fe65d941700)

可以见到,两个线程地址是不一样的,但是pid父进程都是一样的。

另一个例子

主线程接受一个输入num,创建一个线程打印2*num。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <apueerror.h>

// 返回值必须是void *(无类型指针),参数也必须是void *
void *tfn(void *arg)
{
    //传进来的是(void *),强制类型转换
    int num = (int)arg;
    long d2num = 2*num;
    printf("In thread %lu arg: %d.\n", (unsigned long)pthread_self(), num);
    sleep(1);
    printf("Thread over! arg: %d\n", num);
    return  (void*)d2num;
}

void main(int argc, char *argv[])
{
    pthread_t tid;
    long num;
    void *tret; //获取线程终止状态
    while(scanf("%ld", &num) == 1){
        pthread_create(&tid, NULL, tfn, (void *)num);
        //线程终止
        pthread_join(tid, &tret);
        printf("Thread exit code: %ld\n", (long)tret);
    }

    printf("Main thread %lu is over.\n", (unsigned long)pthread_self());
}

因为在Unix环境高级编程的源代码里代码都是使用makefile链接的,小弟不懂,所以直接将代码copy到已有的文件名中跑了。
下面是结果:
在这里插入图片描述
可以看到结果:创建的线程和主线程id号是不一样的。
另外:我觉的在
pthread_create(&tid, NULL, tfn, (void *)num);
直接将num转为指针有点别扭,于是这样:
pthread_create(&tid, NULL, tfn, (void *)&num);
然后在tfn函数中将:
int num = (int)arg;
改为:
int num = *(int*)arg;
也是可以的。

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐