线程一些基本概念及相关基础函数(创建线程,获取线程号,退出线程,回收线程资源,取消线程,设置线程分离属性)

目录

一.线程概念理解

1.定义

2.从进程与线程之间的区别和联系来理解线程

二.线程相关的函数

1.创建线程函数

2.获取调用线程tid函数

3.线程退出函数

4.回收线程函数

5.取消线程函数

6.将线程设置成分离态

7.其他线程函数的学习方法


一.线程概念理解

1.定义

线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

2.从进程与线程之间的区别和联系来理解线程

  • 线程是轻量级的进程,两者创建函数在底层的clone函数;
  • 进程可以蜕化成线程,当一个进程只有一个线程的时候,可以说这个进程是只有一个主线程的进程;
  • 从内核看进程和线程都是一样的,都有不同的PCB,但是PCB中指向内存资源的三级页表是相同的(linux中是四级页表,经典UNIX中是三级页表);
  • 简洁地说,有些人认为线程就是寄存器和内核栈;
  • 在linux下,线程是最小的执行单位,进程是最小的分配资源单位。
  • ...

二.线程相关的函数

1.创建线程函数

头文件及函数原型:
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);


函数参数解释:
pthread_t *thread:传递一个pthread_t类型的变量地址过来,用于保存新线程的tid(线程ID)
const pthread_attr_t *attr:线程属性设置,如果使用默认属性,则传递NULL;这个可以设置线程的栈大小,如果想要定制,可以自己设置.
void *(*start_routine) (void *):函数指针,指向新线程应该加载指向的函数模块;
void *arg:指定线程将要将在调用的那个函数的参数。


返回值:
成功返回0,失败返回错误号,错误码是从1开始编号的。

其他及注意事项:
1.Compile and link with -pthread.(编译的时候记得要链接库文件libpthread.so)
2.typedef unsigned long int pthread_t;(32位linux机器);
3.要注意以前学过的系统函数都是成功返回0,失败返回-1,错误号保存在全局变量errno中,pthread库的函数都是通过返回值返回错误号,虽然每个线程也有一个errno,但是为了兼容其他函数接口提供的,pthread库中本身并不适用它,通过返回值返回错误码更加清晰。

工作步骤:
1.创建线程;
2.将线程id号填到tid中;
3.返回函数调用。

2.获取调用线程tid函数

NAME
       pthread_self - obtain ID of the calling thread

SYNOPSIS(概要)
       #include <pthread.h>
       pthread_t pthread_self(void);
       Compile and link with -pthread.
DESCRIPTION(描述)
       The pthread_self() function returns the ID of the calling thread.  This is the same value that is returned in *thread in the pthread_create(3) call that created this thread.
       (这个函数返回被调用线程的ID,这值与pthread_create中创建新线程成功时出参值thread是一样的)
       (以上是根据官方描述给出的翻译,但是根据上面线程创建的过程来说,线程创建并不是原子操作,可能线程创建好了就去执行线程而并没有把tid赋值好就完成了线程的执行,导致此时再赋值这个tid已经没有意义,这两个值在复杂环境下是否一样,还需要再进行验证)

RETURN VALUE(返回值)
       This function always succeeds, returning the calling thread's ID.
       (这个函数总是会成功的,它返回了调用这个函数的线程的线程号.)
ERRORS
       This function always succeeds.
       (这个函数不会出错.)

注意:
这里的thread_id的值是在进程中的一个标志值,与在系统中的那个LWP的值是不一样的.

3.线程退出函数

SYNOPSIS
       #include <pthread.h>
       void pthread_exit(void *retval);
       Compile and link with -pthread.
DESCRIPTION
       退出当前线程
RETURN VALUE
       This function does not return to the caller.
ERRORS
       This function always succeeds.
注意:
    1.注意pthread_exit函数与exit函数的区别,任何一个线程调用exit函数会导致整个进程退出,任何一个线程调用pthread_exit函数只会导致退出当前线程。
    2.pthread_exit或者return返回的时指针指向的内存单元必须是全局户或者是用malloc分配的,不能再线程函数的栈上分配,因为当其他线程得到这个返回指针时线程函数已经退出了。

4.回收线程函数

NOTICE:
       具有阻塞属性,功能:回收一个线程的线程值并且释放线程的PCB,与进程中的waitpid很像.
NAME
       pthread_join - join with a terminated thread
SYNOPSIS
       #include <pthread.h>
       int pthread_join(pthread_t thread, void **retval);
       Compile and link with -pthread.
参数解释:
       pthread_t thread 回收线程的pid
       void **retval    接受退出线程传递出的返回值
DESCRIPTION
       The  pthread_join()  function  waits for the thread specified by thread to terminate.  If that thread has already terminated, then pthread_join() returns immediately.  The thread specified by thread  must be joinable.
       If retval is not NULL, then pthread_join() copies the exit status of the target thread (i.e., the value that the target thread supplied to pthread_exit(3)) into the location pointed to  by  *retval.
       If the target thread was canceled, then PTHREAD_CANCELED is placed in *retval.
       If  multiple threads simultaneously try to join with the same thread, the results are undefined.  If the thread calling pthread_join() is canceled, then the target thread will remain joinable (i.e.,it will not be detached).

RETURN VALUE
       On success, pthread_join() returns 0; on error, it returns an error number.

ERRORS
       EDEADLK A deadlock was detected (e.g., two threads tried to join with each other); or thread specifies the calling thread.
       EINVAL thread is not a joinable thread.
       EINVAL Another thread is already waiting to join with this thread.
       ESRCH  No thread with the ID thread could be found.

说明:调用该函数的线程将挂起等待,直到id为thread的线程终止,thread线程以不同的方法终止,通过pthread得到的终止状态是不同的,总结如下:
      1.如果thread线程是通过return返回,retval所指向的单元里存放的是thread线程函数的返回值;
      2.如果thread线程被别的线程调用pthread_cancle异常终止掉,retval所指向的单元里存放的是PTHREAD_CANCLED;
      3.如果thread线程是自己调用pthread_exit终止的,retval所指向的单元存放的是传给pthread_exit的参数;
      4.如果对thread线程的终止状态不感兴趣,可以传NULL给retval参数。


5.取消线程函数

NOTICE:
      同一进程内的线程取消隶属同一个进程的其他线程,只是终止一个线程,并不回收线程资源.
NAME
       pthread_cancel - send a cancellation request to a thread
SYNOPSIS
       #include <pthread.h>
       int pthread_cancel(pthread_t thread);
       Compile and link with -pthread.
DESCRIPTION
       The  pthread_cancel()  function sends a cancellation request to the thread thread.  Whether and when the target thread reacts to the cancellation request depends on two attributes that are under the
       control of that thread: its cancelability state and type.
       A thread's cancelability state, determined by pthread_setcancelstate(3), can be enabled (the default for new threads) or disabled.  If a thread has disabled cancellation, then a cancellation request
       remains queued until the thread enables cancellation.  If a thread has enabled cancellation, then its cancelability type determines when cancellation occurs.
       A  thread's  cancellation type, determined by pthread_setcanceltype(3), may be either asynchronous or deferred (the default for new threads).  Asynchronous cancelability means that the thread can be
       canceled at any time (usually immediately, but the system does not guarantee this).  Deferred cancelability means that cancellation will be delayed until the thread next calls a function that  is  a
       cancellation point.  A list of functions that are or may be cancellation points is provided in pthreads(7).
       When a cancellation requested is acted on, the following steps occur for thread (in this order):
       1. Cancellation clean-up handlers are popped (in the reverse of the order in which they were pushed) and called.  (See pthread_cleanup_push(3).)
       2. Thread-specific data destructors are called, in an unspecified order.  (See pthread_key_create(3).)
       3. The thread is terminated.  (See pthread_exit(3).)
       The  above  steps  happen  asynchronously with respect to the pthread_cancel() call; the return status of pthread_cancel() merely informs the caller whether the cancellation request was successfully queued.
       After a canceled thread has terminated, a join with that thread using pthread_join(3) obtains PTHREAD_CANCELED as the thread's exit status.  (Joining with a thread is the only way to know that  cancellation has completed.)

RETURN VALUE
       On success, pthread_cancel() returns 0; on error, it returns a nonzero error number.(成功返回0,失败返回errno)
ERRORS
       ESRCH  No thread with the ID thread could be found.
注意:
    被取消的线程的退出值,定义在Linux中的pthread库中常熟PTHREAD_CANCLED的值是-1,可以在头文件pthread.h中找到它的定义。#define PTHREAD_CANCLED ((void *) -1)

6.将线程设置成分离态

NOTICE:
    线程被设置成分离态之后,调用结束后系统会自动回收该线程的资源,不需要用pthread_join()去回收分离态线程,分离态的线程是不可被pthread_join()回收的.
      
NAME
       pthread_detach - detach a thread
SYNOPSIS
       #include <pthread.h>
       int pthread_detach(pthread_t thread);
       Compile and link with -pthread.
DESCRIPTION
       The  pthread_detach() function marks the thread identified by thread as detached.  When a detached thread terminates, its resources are automatically released back to the system without the need for another thread to join with the terminated thread.
       Attempting to detach an already detached thread results in unspecified behavior.
RETURN VALUE
       On success, pthread_detach() returns 0; on error, it returns an error number.
ERRORS
       EINVAL thread is not a joinable thread.
       ESRCH  No thread with the ID thread could be found.
说明:
    一般情况下,线程终止后,其终止状态一直保留到其他线程调用pthread_join来获取它的状态为止。但是我们的线程也可以设置成detach状态,这样的线程一旦终止就立刻回收它所占用的所有资源,而不保留终止状态,不能对一个已经处于detach状态的线程调用pthread_join,这样的调用将会返回EINVAL。对一个尚未detach的线程调用pthread_join或者pthread_attach都可以把该线程置为detach状态,也就是说,不能对统一线程调用两次pthread_join,或者如果已经对一个线程调用了pthread_detach就不嗯能够再调用detach_join了.

7.设置线程名

8.获取线程名

#include <sys/prctl.h>
static char tname[16];
static char* get_current_threadname(){
    prctl(PR_GET_NAME, tname);
    return tname;
}
 
//#define P_LOGI(fmt, ...) ALOGI("[%s ],tid:%u,%s,F:%s:%d,Fun:%s " fmt,(char*)get_current_threadname(), (unsigned int)gettid(),mark_label,(char*)__FILE__,__LINE__,(char*)__FUNCTION__,##__VA_ARGS__)
  

8.其他线程函数的学习方法

在linux终端上敲命令:man -k pthread 可以列出线程相关的接口函数,列出之后可对这些接口进行学习。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值