Linux_5.1_多线程



1. 线程概念

   进程和线程之间的区别

1.1 Linux进程与线程

        Linux进程创建一个新线程时,线程将拥有自己的栈(因为线程有自己的局部变量),但与它的创建者共享全局变量、文件描述符、信号句柄和当前目录状态。

Linux通过fork创建子进程与创建线程之间是有区别的:fork创建出该进程的一份拷贝,这个新进程拥有自己的变量和自己的PID,它的时间调度是独立的,它的执行几乎完全独立于父进程。

进程可以看成一个资源的基本单位,而线程是程序调度的基本单位,一个进程内部的线程之间共享进程获得的时间片。


2. 函数学习


线程标识
  线程ID
    •进程ID在整个系统中是唯一的
    •线程ID只在它所属的进程环境中有效
函数: pthread_self()

线程标识
  pthread_t类型通常用结构来表示
  •不能把它作为整数处理
    –Linux使用无符号长整数表示
  •为了移植,使用函数来比较线程ID
函数: pthread_equal()

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

int main(void)
{
    pthread_t thread_id;
    /*obtain ID of the calling thread*/
    thread_id = pthread_self();
    printf("Thread ID: %lu \n",thread_id);

    if(pthread_equal(thread_id,pthread_self()))
    {
        printf("Equal!\n");
    }
    else
    {
        printf("Not equal!\n");
    }


    return 0;
}

执行结果:

Thread ID: 0 
Equal!




pthread_create函数原型:

pthread_create 创建一个新线程

所需头文件

#include <pthread.h>

函数说明

在函数调用时创建一个新线程

函数原型

int pthread_create(pthread_t *thread,const pthread_attr_t *attr, void *(*start_routine) (void*),void *arg);

函数传入值

thread           

线程标识符


attr

线程属性设置(通常取值为NULL)

start_routine               

线程函数的起始地址,是一个指向void的在指针作为参数和返回值的函数指针

arg

传递给start_routine的参数



函数返回值

成功:0

错误:返回错误码

错误代码

EAGAIN:创建其他线程时资源不足,或者遇到系统限制线程数.

EINVAL:在attr的设置无效

EPERM:没有权限在attr设置调度规则和参数指定



pthread_join函数原型:

pthread_join 等待线程

所需头文件

#include <pthread.h>


函数说明

调用该函数的线程将挂起,等待 thread 所表示的线程的结束.

函数原型

int pthread_join(pthread_t thread, void ** retval)

函数传入值

thread

等待线程的标识符


retval

用户定义的指针,用来存储被等待线程结束时的返回值(不为NULL时)



函数返回值

成功:0

出错:返回错误码


错误代码

EDEADLK:检测到一个死锁,或者thread指定为调用线程

EINVAL: thread 不是一个等待线程

EINVAL: 其他线程正在等待连接这个线程
ESRCH: 没有找到thread的线程ID

等待线程

  •由于一个进程中的多个线程是共享数据段的,通常在线程退出之后,退出线程所占用的资源并不会随着线程的终止而得到释放

  •pthread_join()函数

    类似进程的wait()/waitpid()函数,用于将当前线程挂起来等待线程的结束
    是一个线程阻塞的函数,调用它的线程一直等待到被等待的线程结束为止
    函数返回时,被等待线程的资源就被收回


pthread_exit函数原型:

 pthread_exit 终止线程调用

所需头文件

#include <pthread.h>

函数说明

 终止线程调用

函数原型

 void pthread_exit(void *retval)

函数传入值

retval     

线程结束时的返回值,可由其它函数如pthread_join()来获取


 



函数返回值


错误代码

这个函数总是成功

退出线程
  •在线程函数运行完后,该线程也就退出了
  •或使用函数pthread_exit(),这是线程的主动行为
  •不能使用exit()
使调用进程终止,所有线程都终止了




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

void *thrd_func1(void *arg);
void *thrd_func2(void *arg);

pthread_t tid1,tid2;

int main(void)
{
    /*create thread "tid1",thread function "thrd_func1"*/
    if(pthread_create(&tid1,NULL,thrd_func1,NULL))
    {
        printf("Create thread 1 error!\n");
        exit(1);
    }
    /*create thread "tid2",thread function "thrd_func2"*/
    if(pthread_create(&tid2,NULL,thrd_func2,NULL))
    {
        printf("Create thread 2 error!\n");
        exit(1);
    }

    /*wait thread "tid1" exit*/
    if(pthread_join(tid1,NULL)!=0)
    {
        printf("Join thread 1 errot!\n");
        exit(1);
    }
    else
    {
        printf("Thread 1 Joined!\n");
    }

    /*wait thread "tid2" exit*/
    if(pthread_join(tid2,NULL)!=0)
    {
        printf("Join thread 2 errot!\n");
        exit(1);
    }
    else
    {
        printf("Thread 2 Joined!\n");
    }

 return 0;
}

void *thrd_func1(void *arg)
{
    /*set other threads can 'cancel' current thread */
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);

    while(1)
    {
        printf("Thread 1 is running!\n");
        sleep(1);
    }
    pthread_exit((void*)0);

}

void *thrd_func2(void *arg)
{
    printf("Thread 2 is running\n");
    sleep(5);
    /*tid1 send 'cancel'to tid1 */
    if(pthread_cancel(tid1)==0)

     printf("Send Cancel cmd to Thread 1. \n");
    }
    pthread_exit((void *)0);
}


编译:

        gcc pthread_create.c -lpthread -o pthread_create



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值