linux C总结篇(线程)上

(百度百科来凑数的,哈哈~~~) 线程:有时被称为轻量级进程,是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。

创建线程:

创建线程函数:

   #include <pthread.h>
   int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

参数说明:1. thread:pthread_t类型的指针 ,用来返回所创建的线程的ID (非负数)

2.attr :指定线程的属性。默认为NULL 。稍后介绍

3.start_routine:线程创建后所要调用的函数,这是一个函数指针。

插曲( 指针函数与函数指针的简单区别):
指针函数:int *f(int a, int b);
函数指针:int (*f)(int a, int b);

说明: 函数指针就是用括号把你的函数名括起来,加一个*号。指针函数就是加一个*号

4.arg:传递给线程函数的参数 。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
typedef struct {
    int a;
    int b;
}TT ;
void *creat_pthread(void *arg)
{
    TT *p = (TT *)arg;
    pthread_t newthid ;
    int i;
    newthid=pthread_self() ;
    printf("the new  pthread ID is %u 
",newthid) ;
    for(i= 0 ;i< (p->a)  ; i++ )
       printf("---------------------------%d
",i );
    return NULL ;
}
int main(void)
{
    TT *p = (TT *)malloc(sizeof(TT)) ;//注意开辟空间,我就被坑在这里了@~@
    pthread_t thid ; 
    int n  ,i;
    p->a= 100 ;
    p->b= 30 ; 
    printf("%d %d
",p->a,p->b);
    printf("the main  pthread ID is %u 
",pthread_self()) ;
    if(pthread_create(&thid ,NULL ,creat_pthread ,(void *)p) != 0)
    {
        printf("creat pthread is failed !! 
");
        exit(-1);
    }
    for(i= 0;i<  100;i++)
        printf("+++++++++++++++++++++++%d
",i);
    sleep(5);
    exit(0);
}

执行结果:

这里写图片描述

注意事项:

1.如果调用函数返回一个void 指针,则不需要强转。

2. 参数arg ,必须强转为void * 的类型,然后再在调用函数中转回来即可

3.传递多个参数时,必须申明一个结构体来包含所有的参数,然后再传入线程函数其实也是一个封装的思想了

4.结果也说明,线程执行顺序是不确定的,是由CPU 的调度算法(时间片的分配)所决定的 。

一些简单函数的说明:

  pthread_t pthread_self(void);//取得本线程ID 
  int pthread_equal(pthread_t t1, pthread_t t2);//判断两个线程ID 是否指向同一个线程
 int pthread_once(pthread_once_t *once_control,void (*init_routine)(void)); //保证init_routine 线程函数在进程中只执行一次

线程属性 :

该结构体是

 typedef struct
 {
 int   detachstate;     线程的分离状态
 int    schedpolicy;   线程调度策略
struct sched_param    schedparam;   线程的调度参数
 int        inheritsched;    线程的继承性
 int        scope;          线程的作用域
 size_t     guardsize; 线程栈末尾的警戒缓冲区大小
 int        stackaddr_set;
 void *     stackaddr;      线程栈的位置
 size_t     stacksize;       线程栈的大小
 }pthread_attr_t;

参数说明:

schedpolicy:线程调度策略,只要有三种:(1)正常非实时。(2):实时,轮转。(3):实时,先入先出。(后两种调度只对root 用户有效)

schedparam :一个struct sched_param 结构体,其中有一个sched_priority 表示线程优先级,只有当调度策略为实时才有效,缺省为0

scope:线程优先级有效范围

线程终止(两种):

1.return 返回

2. 使用pthread_exit()函数:

  #include <pthread.h>
 void pthread_exit(void *retval);

两种特殊情况:

1.在主线程中线程过早返回或者是调用exit 函数,则整个进程都会终止。就会导致所有的线程终止 。

2.在主线程中线程调用pthread_exit函数退出,进程不会结束,直到所有线程结束,进程才会结束

资源释放:

有些资源必须在一段时间内被一个线程所持有,其他线程使用资源时提出申请,也就是我所说的厕所的问题。现在我们假设一种情况,如果一个线程在终止时并没有释放资源,那么其他线程也无法使用,这就会导致死锁!!那么linux 该如何解决这个问题呐???

linux 系统提供了一对函数用于主动释放资源

   #include <pthread.h>

   1.void pthread_cleanup_push(void (*routine)(void *),
                             void *arg);
   2.void pthread_cleanup_pop(int execute);

说明:1.这两个函数的调用之间的程序段中的终止动作都会执行pthread_cleanup_push所指定的清除函数。

2.pthread_cleanup_push带有一个{ ,pthread_cleanup_pop带有一个},因此这两个函数必须成对出现,且必须位于程序的同一段代码中才能编译通过。

线程间的同步(相当于进程中的wait 函数)

   #include <pthread.h>

   int pthread_join(pthread_t thread, void **retval);

说明:1.pthread_join用来等待一个线程的结束,调用pthread_join的线程被挂起,回收所等待线程的资源。

2.一个线程只允许一个线程使用pthread_join来等待

3.被等待的线程应该处于”join”的状态,而非死亡状态(DETACHED)

4.为避免内存泄漏,因此所有的线程终止时,必须处于两种情况之中(1.死亡状态(DETACHED)2.使用pthread_join和回收资源)

小示例:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
int *creat_pthread(int *n  )
{
    pthread_t newthid ;
    int i;
    newthid=pthread_self() ;
    printf("the new  pthread ID is %d 
",newthid) ;
    for(i= 0 ;i< *n ;i++)
       printf("------------------------%d
",i );
    pthread_exit((void *)-100);
}
int main(void)
{
    pthread_t thid ; 
    int n  ,i;
    int status ;
    printf("main pthread ID is %d 
",pthread_self());
    printf("please input  the   n :  ");
    scanf("%d",&n);
    if(pthread_create(&thid ,NULL ,(void *)creat_pthread ,&n) != 0)
    {
        printf("creat pthread is failed !! 
");
        exit(-1);
    }
    pthread_join(thid,(void *)&status);
    printf("the new pthread's exit number is %d 
",status);
    exit(0);
}

执行结果:

这里写图片描述

说明:1.status 存放新开的线程的退出码(-100)

2.pthread_join 阻塞主线程,等待新开的线程结束。(类似于函数的调用)

感觉后面的要介绍的内容过于多了一点,因此分成两个部分来叙述。望谅解!!!

原文地址:https://www.cnblogs.com/Tattoo-Welkin/p/10335339.html