linux多线程

线程和进程

进程是系统分配资源的基本单位,线程是CPU调度的基本单位;启动一个程序,可能开启一个或多个进程,一个进程可以拥有多个线程,每个进程都有一个主线程。

线程的相关函数

创建一个线程:

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
函数功能:在进程里创建一个新的线程
函数参数:
thread----->一个线程id的地址
attr----->线程的属性
start_routine----->线程执行函数
arg----->传递给程序函数的唯一的一个参数
返回值:成功返回0,失败返回错误码。

主动挂起一个线程:

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
函数功能:使调用此函数的线程被挂起,等待线程id为thread的线程终止后,回收这个线程的资源;被挂起的线程的属性必须是连接属性(即将pthread_create()函数的第二个参数设置为NULL,就默认这个线程是连接状态)。
参数:
thread----->被等待的线程id
retval----->不为NULL时,retval指向为被等待线程终止时的返回值
返回值:成功返回0,失败返回错误码

终止一个线程:
可以使用return语句和exit()函数:
在主线程里使用来二者其一的话,会使得整个进程终止,其他还在运行的线程也会被终止;
除主线程外的线程使用二者其一,会使线程主动终止,不会影响主线程。

#include <pthread.h>
void pthread_exit(void *retval);
函数功能:主动结束调用此函数的线程
参数:
retval----->指向线程返回值的指针
返回值:没有返回值

#include <pthread.h>
int pthread_cancel(pthread_t thread);
函数功能:向一个线程发送终止信号
参数:
thread----->接受终止信号的线程id
返回值:成功返回0;失败返回非0值。
(向线程发送终止信号后,并不一定会使的线程终止,可以用int pthread_setcancelstate(int state, int *oldstate)函数来设置线程对终止信号的响应,第一个参数state为PTHREAD_CANCEL_ENABLE(缺省)时执行终止信号,为PTHREAD_CANCEL_DISABLE时忽略终止信号继续执行,第二个参数不为NULL时,就用oldstate保留线程的状态信息。)

设置线程的属性:

pthread_attr_t attr 线程属性
线程为连接属性的话,一般由其他线程调用pthread_join来释放线程的资源;线程为分离属性的话,线程结束后,由系统释放线程资源。
①初始化线程属性变量:
int pthread_attr_init(pthread_attr_t *attr);
②设置线程属性变量为分离态或非分离态:
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
参数detachstate为PTHREAD_CREATE_DETACHED(分离态)或PTHREAD_CREATE_JOINABLE(非分离态)
③利用pthread_create来创建线程:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
④销毁线程属性变量:
int pthread_attr_destroy(pthread_attr_t *attr); //销毁线性属性变量

打印线程id:

#include <pthread.h>
pthread_t pthread_self(void);
函数功能:打印线程id
参数:没有参数
返回值:成功返回线程id;不会执行失败。

练习:

1、创建一个线程,在该线程里打印命令行参数,在主线程里利用pthread_join来实现线程间同步,并释放被等待线程的资源:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

struct main_arg
{
    int num_arg;
    char **pp_arg;
};

void *thread_func(void *arg)
{
    printf("thread start...\n");
    struct main_arg *p = (struct main_arg *)arg;

    for(int i = 0; i < p->num_arg; ++i)
        printf("%s\n", *(p->pp_arg + i) );        //打印命令行参数

    printf("thread end...\n");   

    pthread_exit(NULL);
}


int main(int argc, char const *argv[])
{
    struct main_arg arg;
    arg.num_arg = argc ;
    arg.pp_arg = (char**)&argv[0];
    
    pthread_t tid;  
    int ret = pthread_create(&tid, NULL, thread_func, (void*)&arg);
	if(ret != 0)
	{
		perror("pthread_create");
		return -1;
	}
    pthread_join(tid, NULL);  //主线程挂起,等待线程结束,回收线程的资源

    return 0;
}

在这里插入图片描述

2、创建一个线程,将这个线程的属性设置为分离属性,在该线程里打印命令行参数:

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

struct main_arg
{
    int num_arg;
    char **pp_arg;
};

void *thread_func(void *arg)
{
    printf("thread start...\n");
    struct main_arg *p = (struct main_arg *)arg;

    for(int i = 0; i < p->num_arg; ++i)
        printf("%s\n", *(p->pp_arg + i) );        //打印命令行参数

    printf("thread end...\n");   

    pthread_exit(NULL);
}

int main(int argc, char const *argv[])
{
    struct main_arg arg;
    arg.num_arg = argc ;
    arg.pp_arg = (char**)&argv[0];

    pthread_attr_t attr;    //线程属性
    pthread_attr_init(&attr);   //初始化线程属性变量
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);    //将线程属性设置为分离态
    
    pthread_t tid;  
    int ret = pthread_create(&tid, &attr, thread_func, (void*)&arg);  //创建分离态的线程
    if(ret != 0)
    {
        perror("pthread_create");
        return -1;
    }

    sleep(1);   //主线程挂起1秒,等待新创建的线程结束

    pthread_attr_destroy(&attr);    //销毁线程属性变量

    return 0;
}

在这里插入图片描述

结果分析:
练习2里新创建的线程结束后虽然可以由系统自动释放其资源,但是因为将新创建的线程被设置为了分离态,所以,新线程和主线程之间的执行先后顺序不确定。而使用pthread_join就可以即完成线程之间的同步,又可以保证结束的线程的资源被及时回收。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值