线程

三、linux最小资源单位。 -- 线程。
1、 进程与线程的区别?
linux  ---  社会
进程   ---  人
线程   ---  人的手

线程是一个进程的内部资源。

2、如何开启一个进程? 如何开启一个线程?
./xxxx  -> 开启一个进程

xxxx.c
int main(int argc,char *argv[])
{
    /* 代表进程的开始 */
    xxxx;

    /* 进程的运行过程 */
    ---> 可以使用函数创建很多个线程。


    /* 代表进程的结束,就会导致这个进程内部的所有线程都退出 */
    return 0;
}

四、线程的函数接口?
线程中所有函数接口都是在线程库中,所以都是查看man手册的第3手册。

1、 如何创建一个子线程?   -> pthread_create()  -> man 3 pthread_create
功能: create a new thread
    //创建一个子线程

头文件:
    #include <pthread.h>

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

参数:
    thread:存放线程ID号的变量的地址。
    attr:线程的属性  普通属性 -> NULL
    start_routine:线程的例程函数(子线程需要做的事情,把这些事情放在一个函数中即可,函数必须长:void *fun(void *arg))          arg:传递给子线程例程函数的参数,如果不需要传递,则填NULL。

返回值:
    成功:0
    失败:非0


注意:
Compile and link with -pthread.
//如果你使用了该函数,则编译时必须链接线程库。

本来: gcc xxx.c -o xxx
现在: gcc xxx.c -o xxx -lpthread

gec@ubuntu:/mnt/hgfs/GZ2057/09 系统编程/05/code$ gcc pthread_create.c -o pthread_create
/tmp/ccl10xXX.o: In function `main':
pthread_create.c:(.text+0x75): undefined reference to `pthread_create'  -> 没有链接线程库
collect2: error: ld returned 1 exit status

2、 案例
    尝试在进程中创建一个子线程,让主线程做一件事情,让子线程也去做一件事情,看看会不会同时做。

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

//子线程
void *my_fun(void *arg)
{
    //4. 子线程每隔2S打印一句话appletree,一共打印6S。
    int i;
    for(i=0;i<3;i++)
    {
        printf("appletree!\n");
        sleep(2);
    }
}

int main(int argc,char *argv[])
{
    //1. 现在还是一个单进程的程序。
    printf("singal process!\n");
    
    //2. 创建一个子线程。
    //   本来的进程叫做主线程。
    pthread_t tid;
    pthread_create(&tid,NULL,my_fun,NULL);
    
    //3. 主线程每隔1S打印一句话helloworld,一共打印10S。
    int i;
    for(i=0;i<10;i++)
    {
        printf("helloworld!\n");
        sleep(1);
    }
    
    return 0; //进程退出,都会导致这个进程中所有的线程都会退出。
}

3、 接合线程。  -> pthread_join()  -> man 3 pthread_join
功能: pthread_join - join with a terminated thread
        //接合一个结束的线程。

头文件:
    #include <pthread.h>

原型:
    int pthread_join(pthread_t thread, void **retval);

参数:
    thread: 需要接合的线程的ID号。
    retval: 子线程的退出值,如果不关心,则填NULL。

返回值:
    成功:0
    失败:非0

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

//子线程
void *my_fun(void *arg)   //arg = (void *)&a
{
    printf("a = %d\n",*(int *)arg);
    
    //4. 子线程每隔2S打印一句话appletree,一共打印6S。
    int i;
    for(i=0;i<10;i++) // 10S 
    {
        printf("helloworld!\n");
        sleep(1);
    }
}

int main(int argc,char *argv[])
{
    //1. 现在还是一个单进程的程序。
    printf("singal process!\n");
    
    //2. 创建一个子线程。
    //   本来的进程叫做主线程。
    pthread_t tid;
    int a = 100;
    pthread_create(&tid,NULL,my_fun,(void *)&a);
    
    //3. 主线程每隔1S打印一句话helloworld,一共打印10S。
    int i;
    for(i=0;i<3;i++)  //6S 
    {
        printf("appletree!\n");
        sleep(2);
    }
    
    //4. 接合线程
    pthread_join(tid,NULL);  //等待子线程退出了,这个函数才返回!
    
    return 0; //进程退出,都会导致这个进程中所有的线程都会退出。
}

 

一、主线程如何知道子线程怎么退出的?

//子线程
void *fun(void *arg)
{
    
}

pthread_join(tid,NULL);  -> 只等待子线程,但是不关心子线程的退出值。
pthread_join(tid,不为NULL);  -> 除了会等到子线程,还会接收子线程退出值。  -> 但是子线程要主动返回它自己的退出值。

二、子线程如何退出的?如何返回退出值?  -> pthread_exit()  -> man 3 pthread_exit
1、 函数功能:
功能: pthread_exit - terminate calling thread
            //结束一个正在运行的线程

头文件:
    #include <pthread.h>

原型:
       void pthread_exit(void *retval);

参数:
    retval:退出值的地址   -> 不能是局部变量,只能是全局

返回值:无

//子线程的退出值不能是局部变量
//因为:
int state1 = 20;  -> 全局不会释放。

void *fun(void *arg)
{
    int state2 = 10; //局部变量  ->局部变量的空间会释放。
    pthread_exit(&state1);     

2、 子线程退出与主线程接合结合一起使用。   

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

int state = 9;   //子线程的退出值

void *fun(void *arg)
{
    //子线程工作内容
    int i;
    for(i=0;i<5;i++)
    {
        printf("helloworld!\n");
        sleep(1);
    }
    
    //2. 子线程主动返回退出值。
    pthread_exit((void *)&state);   
}

int main(int argc,char *argv[])
{
    //1. 直接创建一个子线程
    pthread_t tid;
    pthread_create(&tid,NULL,fun,NULL);
    
    //3. 主动接合线程,并且接收子线程的退出值。
    void *p = NULL;
    pthread_join(tid,&p);  -> p就是指向子线程的退出值。
    
    int ret_value = *(int*)p;
    printf("exit_state = %d\n",ret_value);
    
    if(ret_value == 10)  //如果等于10,就代表主线程知道子线程是正常退出的
    {
        printf("ok!\n");
    }
    else{  //异常退出
        printf("error!\n");
    }
}

三、导致线程退出的几种情况。
The new thread terminates in one of the following ways:
以下的情况的其中一种都会导致线程的退出。

* It calls pthread_exit(3), specifying an exit status value that is available to another thread in the  same  process  that  calls pthread_join(3).
//当线程调用pthread_exit()函数可以导致退出,还可以将退出值返回给那个接合它的线程。

* It returns from start_routine().  This is equivalent to calling pthread_exit(3) with the value supplied in the return statement.
//例程函数返回也会导致退出,return后面可以跟着退出值,这种等价于使用pthread_exit()

* It is canceled (see pthread_cancel(3)).
//线程被取消了,也会导致线程退出。

* Any  of the threads in the process calls exit(3), or the main thread performs a return from main().  This causes the termination of all threads in the process.
在进程中的任意一个线程调用exit(),或者主线程的main函数返回了(进程的退出),都会导致整个进程中所有的线程退出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值