Linux:线程&线程创建&线程终止

线程

1.是操作系统能够进行调度的最小单位
2.线程被包含在进程之中,是进程中的实际运作单位
3.一个线程指的是进程中一个单一顺序的控制流
4.一个进程可以并发多个线程,每个线程执行不同的任务

比如四个人在一个房子里打麻将,创建一个新进程就相当于是在开一个房间,而创建一个新线程是在原有的房间中增加一个人而已
这里写图片描述

线程的优点

1.创建一个新的线程的代价要比创建一个新进程的代价小得多
2.与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多
3.线程占有的资源要比进程少
4.线程之间共享数据更容易(线程是在一个房间中,所以相互通信比较容易,而进程之间通话需要跑到另一个房间)

线程的缺点

1.编码/调试难度提高
因为线程之间谁先执行不确定,在一个是共享资源的问题
2.缺乏访问控制
一个线程崩溃,会导致整个进程都异常终止,一个线程中调用某些函数,会影响整个进程

进程与线程的区别

1.进程:进程(或者任务)是资源分配的基本单位
2.线程:线程(或者轻量级进程)是调度/执行的基本单位
3.线程运行在进程中
4.一个进程至少都有一个线程

进程与线程中函数的对比

这里写图片描述
为什么线程/进程数不是越多越好?

1.线程/进程数目达到一定程度时,就不会再提高程序的执行效率了
2.线程/进程数目过多可能会导致进程异常终止
3.线程/进程数目过多可能会导致线程安全问题(线程安全:多个线程竞争同一资源)

线程创建

pthread_create

功能:创建一个新的线程
头文件:#include<pthread.h>
原型:
 int pthread_create(   pthread_t *pthread, 
                       const pthread_attr_t*attr, 
                       void*(*start_routine)(void*), 
                       void *arg  )
参数说明:
thread:返回线程ID,此参数是一个输出型参数
      (返回的是新创建的线程的ID)

attr:设置线程的属性,attr为NULL表示使用默认属性(一般设为NULL)
    (设置的是新线程的属性)

start_routine:是个函数地址,线程启动后需要执行的函数
             (这是一个函数指针,指向线程的入口函数)

arg:传给线程启动函数的参数
返回值:成功返回0,失败返回错误码

线程被创建后,并不能保证那个线程先执行,新创建的线程和调用线程的执行顺序不确定,由操作系统进行调度

示例

1.创建一个线程
代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
void*ThreadEntry(void*arg)
{
    (void)arg;
    printf("I am thread\n");
}

int main()
{
    pthread_t tid;
    int ret=0;
    ret=pthread_create(&tid,NULL,ThreadEntry,NULL);
    if(ret!=0)
    {
        perror("pthread_create");
        exit(1);
    }
    printf("I am main\n");
    sleep(1);
 //让主线程睡眠1秒,是为了不让此线程跑的太快使整个进程结束
 //如果主线程跑的太快,新创建的线程还没来的及执行,整个进程就已经结束了
    return 0;
}

运行结果:
这里写图片描述

2.使用死循环来创建线程(死循环是为了防止主线程跑的太快,而使新创建的线程没有机会执行,让它循环多次相当于是等待新线程启动和执行)
代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
void*ThreadEntry(void*arg)
{
    (void)arg;
    while(1)
    {
        printf("I am thread,%1x\n",pthread_self());
        sleep(1);
    }
}
int main()
{
    int ret=0;
    pthread_t tid;
    ret=pthread_create(&tid,NULL,ThreadEntry,NULL);
    if(ret!=0)
    { 
        perror("pthread_create");
        exit(1);
    }
    while(1)
    {
        printf("I am main,%1x\n",pthread_self());
        sleep(1);
    }
    return 0;
}

pthread_self()是得到当前线程的ID

线程创建函数在libpthread.so库中,所以在编译时需要将该库导入,命令如下:
例如编译create.c
gcc create.c -lpthread
就是说在编译时需要加上 "-lpthread"

运行结果:
这里写图片描述

线程终止

如果需要终止某个线程,而不终止整个进程,有以下三种方法:

1.从需要终止的线程函数中直接return
ps:这种方法对主线程不适用,因为从main函数return相当于调用exit,会使main函数直接退出
2.需要终止的线程可以调用pthread_exit()来终止自己
3.一个线程可以调用pthread_cancel来终止同一进程中的其他线程

pthread_exit()


1.功能:终止线程

2.原型:
void pthread_exit(void *value_ptr)
参数说明:
value_ptr:不要指向一个局部变量

3.返回值:
无返回值

pthread_cancel()

1.功能:取消一个执行中的线程

2.原型:
int pthread_cancel(pthread_t thread)
参数说明:
thread:需要取消的线程的ID

3.返回值:
成功返回0,失败返回错误码

1.直接return

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<pthread.h>
void*ThreadEntry(void*arg)
{
    int count=0;
    (void)arg;
    while(1)
    {
        ++count;
        if(count>=5)
            return NULL;
        printf("I am thread,%1x\n",pthread_self());
        sleep(1);
    }
}
int main()
{
int ret=0;
    pthread_t tid;
ret=    pthread_create(&tid,NULL,ThreadEntry,NULL);
if(ret!=0)
{
 perror("pthread_create");
 exit(1);
 }
    while(1)
    {
        printf("I am main,%1x\n",pthread_self());
        sleep(1);
    }
    return 0;
}

运行结果:
这里写图片描述

2.调用pthread_exit()

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
void*ThreadEntry(void *arg)
{
    int count=0;
    (void)arg;
    while(1)
    {
        ++count;
        if(count>=7)
            pthread_exit(NULL);
        printf("I am thread\n");
        sleep(1);
    }
}
int main()
{
    int ret=0;
    pthread_t tid;
    ret=pthread_create(&tid,NULL,ThreadEntry,NULL);
    if(ret!=0)
    {
        perror("ptherad_create");
        exit(1);
    }
    while(1)
    {
        printf("I am main\n");
        sleep(1);
    }
    return 0;
}

运行结果:
这里写图片描述

3.调用pthread_cancel()

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
void *ThreadEntry(void*arg)
{
    (void)arg;
    while(1)
    {
        printf("I am thread\n");
        sleep(1);
    }
}
int main()
{
    int ret=0;
    int count=0;
    pthread_t tid;
    ret=pthread_create(&tid,NULL,ThreadEntry,NULL);
    if(ret!=0)
    {
        perror("pthread_create");
        exit(1);
    }
    while(1)
    {
        ++count;
        if(count>10)
            pthread_cancel(tid);
        printf("I am main\n");
        sleep(1);
    }
    return 0;
}

运行结果:
这里写图片描述

pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用manlloc分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数就已经退出了
示例

1.return返回线程函数栈上分配的变量

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
void*ThreadEntry(void*arg)
{
    (void)arg;
    int a=10;
    int *p=&a;
    printf("I am thread\n");
    return (void*)p;
}

int main()
{
    pthread_t tid;
    void*ret;
    int thread=0;
    thread=pthread_create(&tid,NULL,ThreadEntry,NULL);
    if(thread!=0)
    {
        perror("pthread_create");
        exit(1);
    }
    printf("I am main\n");
    pthread_join(tid,&ret);
    printf("ret=%d\n",*(int*)ret);
    return 0;
}

这里写图片描述

2.pthread_exit中的参数是线程函数在栈上分配的

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
void*ThreadEntry(void*arg)
{
    (void)arg;
    int count=0;
    int a=10;
    int *p=&a;
    while(1)
    {
        ++count;
        if(count>=5)
            pthread_exit(p);
        printf("I am thread\n");
        sleep(1);
    }
}

int main()
{
    pthread_t tid;
    void*ret;
    int thread=0;
    thread=pthread_create(&tid,NULL,ThreadEntry,NULL);
    if(thread!=0)
    {
        perror("pthread_create");
        exit(1);
    }
    printf("I am main\n");
    pthread_join(tid,&ret);
    printf("ret=%d\n",*(int*)ret);
    return 0;
}

这里写图片描述

malloc分配

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
void*ThreadEntry(void*arg)
{
    (void)arg;
    int count=0;
    int *p=(int*)malloc(sizeof(int));
    *p=10;
    while(1)
    {
        ++count;
        if(count>=5)
            pthread_exit(p);
        printf("I am thread\n");
        sleep(1);
    }
}

int main()
{
    pthread_t tid;
    void*ret;
    int thread=0;
    thread=pthread_create(&tid,NULL,ThreadEntry,NULL);
    if(thread!=0)
    {
        perror("pthread_create");
        exit(1);
    }
    printf("I am main\n");
    pthread_join(tid,&ret);
    printf("ret=%d\n",*(int*)ret);
    free(ret);//malloc后记得释放
    return 0;
}

这里写图片描述

全局变量

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
int a=20;
void*ThreadEntry(void*arg)
{
    (void)arg;
    int count=0;
    int*p=&a;
    while(1)
    {
        ++count;
        if(count>=5)
            pthread_exit(p);
        printf("I am thread\n");
        sleep(1);
    }
}

int main()
{
    pthread_t tid;
    void*ret;
    int thread=0;
    thread=pthread_create(&tid,NULL,ThreadEntry,NULL);
    if(thread!=0)
    {
        perror("pthread_create");
        exit(1);
    }
    printf("I am main\n");
    pthread_join(tid,&ret);
    printf("ret=%d\n",*(int*)ret);
    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值