多线程使用

17 篇文章 0 订阅

1. POSIX 线程标准

    POSIX线程标准(POXIS Threads,缩写为Pthreads)是POSIX的线程标准,定义了一系列操作线程
的API。

1.1 POSIX标准

    POSIX标准,POSIX表示可移植操作系统接口,即Portable Operating System Interface of
UNIX,缩写为POSIX。POSIX 标准定义了操作系统为应用程序提供的接口标准,是IEEE为要在各种
UNIX操作系统上运行的软件而定义的一系列 API 标准的总称,其正式称呼为IEEE 1003,而国际标
准名称为ISO/IEC 9945。

    20世纪80年代,unix厂商视图增加一些新的、往往不兼容的特性使特们的程序体现差异化,这样
导致通用性降低,为阻止这一趋势,IEEE开始努力使unix进行标准化开发,后来由 Richard Stallman
命名为“Posix”,从而就得到了一系列标准,称作Posix标准。这套标准涵盖了很多方面,比如Unix系
统调用的C语言接口、shell程序和工具、线程及网络编程。

1.2 Linux上的线程库

    Linux上没有真正意义的线程,使用进程来模拟,属于用户级线程,位于libpthread共享库,
遵循POSIX标准。Linux最有名的两个线程库:LinuxThreads 和 NPTL。 Linux从内核2.6开始,
多线程已经使用NPTL技术。查看系统使用的线程库,getconf GNU_LIBPTHREAD_VERSION。

1.3 线程API

    当前我使用的操作系统CentOS Linux release 7.4.1708,线程库查看如下:
[root@host122 ~]# getconf GNU_LIBPTHREAD_VERSION
NPTL 2.17

查看该系统支持的线程API:

[root@host122 ~]# man -k pthread
pthread_atfork  (3p)  - register fork handlers
pthread_attr_destroy  (3) - initialize and destroy thread attributes object
pthread_attr_getaffinity_np  (3) - set/get CPU affinity attribute in thread attributes object
pthread_attr_getdetachstate  (3) - set/get detach state attribute in thread attributes object
pthread_attr_getguardsize  (3) - set/get guard size attribute in thread attributes object
pthread_attr_getinheritsched  (3) - set/get inherit-scheduler attribute in thread attributes object
pthread_attr_getschedparam  (3) - set/get scheduling parameter attributes in thread attributes object
pthread_attr_getschedpolicy  (3) - set/get scheduling policy attribute in thread attributes object
pthread_attr_getscope  (3) - set/get contention scope attribute in thread attributes object
pthread_attr_getstack  (3) - set/get stack attributes in thread attributes object
pthread_attr_getstackaddr  (3) - set/get stack address attribute in thread attributes object
pthread_attr_getstacksize  (3) - set/get stack size attribute in thread attributes object
pthread_attr_init  (3) - initialize and destroy thread attributes object
pthread_attr_setaffinity_np  (3) - set/get CPU affinity attribute in thread attributes object
pthread_attr_setdetachstate  (3) - set/get detach state attribute in thread attributes object
pthread_attr_setguardsize  (3) - set/get guard size attribute in thread attributes object
pthread_attr_setinheritsched  (3) - set/get inherit-scheduler attribute in thread attributes object
pthread_attr_setschedparam  (3) - set/get scheduling parameter attributes in thread attributes object
pthread_attr_setschedpolicy  (3) - set/get scheduling policy attribute in thread attributes object
pthread_attr_setscope  (3) - set/get contention scope attribute in thread attributes object
pthread_attr_setstack  (3) - set/get stack attributes in thread attributes object
pthread_attr_setstackaddr  (3) - set/get stack address attribute in thread attributes object
pthread_attr_setstacksize  (3) - set/get stack size attribute in thread attributes object
pthread_barrierattr_destroy  (3p) - destroy and initialize the barrier attributes object (ADVANCED REALTIME THREADS)
pthread_barrierattr_getpshared  (3p) - get and set the process-shared attribute of the barrier attributes object (ADVANCED REALTIME THREADS)
pthread_barrierattr_init  (3p) - destroy and initialize the barrier attributes object (ADVANCED REALTIME THREADS)
pthread_barrierattr_setpshared  (3p) - get and set the process-shared attribute of the barrier attributes object (ADVANCED REALTIME THREADS)
pthread_barrier_destroy  (3p) - destroy and initialize a barrier object (ADVANCED REALTIME THREADS)
pthread_barrier_init  (3p) - destroy and initialize a barrier object (ADVANCED REALTIME THREADS)
pthread_barrier_wait  (3p) - synchronize at a barrier (ADVANCED REALTIME THREADS)
pthread_cancel  (3)   - send a cancellation request to a thread
pthread_cleanup_pop  (3) - push and pop thread cancellation clean-up handlers
pthread_cleanup_pop_restore_np  (3) - push and pop thread cancellation clean-up handlers while saving cancelability type
pthread_cleanup_push  (3) - push and pop thread cancellation clean-up handlers
pthread_cleanup_push_defer_np  (3) - push and pop thread cancellation clean-up handlers while saving cancelability type
pthread_condattr_destroy  (3p) - destroy and initialize the condition variable attributes object
pthread_condattr_getclock  (3p) - get and set the clock selection condition variable attribute (ADVANCED REALTIME)
pthread_condattr_getpshared  (3p) - get and set the process-shared condition variable attributes
pthread_condattr_init  (3p) - destroy and initialize the condition variable attributes object
pthread_condattr_setclock  (3p) - get and set the clock selection condition variable attribute (ADVANCED REALTIME)
pthread_condattr_setpshared  (3p) - get and set the process-shared condition variable attributes
pthread_cond_broadcast  (3p) - broadcast or signal a condition
pthread_cond_destroy  (3p) - destroy and initialize condition variables
pthread_cond_init  (3p) - destroy and initialize condition variables
pthread_cond_signal  (3p) - broadcast or signal a condition
pthread_cond_timedwait  (3p) - wait on a condition
pthread_cond_wait  (3p) - wait on a condition
pthread_create  (3)   - create a new thread
pthread_detach  (3)   - detach a thread
pthread_equal  (3)    - compare thread IDs
pthread_exit  (3)     - terminate calling thread
pthread_getaffinity_np  (3) - set/get CPU affinity of a thread
pthread_getattr_np  (3) - get attributes of created thread
pthread_getconcurrency  (3) - set/get the concurrency level
pthread_getcpuclockid  (3) - retrieve ID of a thread's CPU time clock
pthread_getname_np  (3) - set/get the name of a thread
pthread_getschedparam  (3) - set/get scheduling policy and parameters of a thread
pthread_getspecific  (3p) - thread-specific data management
pthread.h  (0p)       - threads
pthread_join  (3)     - join with a terminated thread
pthread_key_create  (3p) - thread-specific data key creation
pthread_key_delete  (3p) - thread-specific data key deletion
pthread_kill  (3)     - send a signal to a thread
pthread_kill_other_threads_np  (3) - terminate all other threads in process
pthread_mutexattr_destroy  (3p) - destroy and initialize the mutex attributes object
pthread_mutexattr_getprioceiling  (3p) - get and set the prioceiling attribute of the mutex attributes object (REALTIME THREADS)
pthread_mutexattr_getprotocol  (3p) - get and set the protocol attribute of the mutex attributes object (REALTIME THREADS)
pthread_mutexattr_getpshared  (3p) - get and set the process-shared attribute
pthread_mutexattr_getrobust  (3p) - get and set the mutex robust attribute
pthread_mutexattr_gettype  (3p) - get and set the mutex type attribute
pthread_mutexattr_init  (3p) - destroy and initialize the mutex attributes object
pthread_mutexattr_setprioceiling  (3p) - get and set the prioceiling attribute of the mutex attributes object (REALTIME THREADS)
pthread_mutexattr_setprotocol  (3p) - get and set the protocol attribute of the mutex attributes object (REALTIME THREADS)
pthread_mutexattr_setpshared  (3p) - get and set the process-shared attribute
pthread_mutexattr_setrobust  (3p) - get and set the mutex robust attribute
pthread_mutexattr_settype  (3p) - get and set the mutex type attribute
pthread_mutex_consistent  (3p) - mark state protected by robust mutex as consistent
pthread_mutex_destroy  (3p) - destroy and initialize a mutex
pthread_mutex_getprioceiling  (3p) - get and set the priority ceiling of a mutex (REALTIME THREADS)
pthread_mutex_init  (3p) - destroy and initialize a mutex
pthread_mutex_lock  (3p) - lock and unlock a mutex
pthread_mutex_setprioceiling  (3p) - get and set the priority ceiling of a mutex (REALTIME THREADS)
pthread_mutex_timedlock  (3p) - lock a mutex (ADVANCED REALTIME)
pthread_mutex_trylock  (3p) - lock and unlock a mutex
pthread_mutex_unlock  (3p) - lock and unlock a mutex
pthread_once  (3p)    - dynamic package initialization
pthread_rwlockattr_destroy  (3p) - destroy and initialize the read-write lock attributes object
pthread_rwlockattr_getpshared  (3p) - get and set the process-shared attribute of the read-write lock attributes object
pthread_rwlockattr_init  (3p) - destroy and initialize the read-write lock attributes object
pthread_rwlockattr_setpshared  (3p) - get and set the process-shared attribute of the read-write lock attributes object
pthread_rwlock_destroy  (3p) - destroy and initialize a read-write lock object
pthread_rwlock_init  (3p) - destroy and initialize a read-write lock object
pthread_rwlock_rdlock  (3p) - lock a read-write lock object for reading
pthread_rwlock_timedrdlock  (3p) - lock a read-write lock for reading
pthread_rwlock_timedwrlock  (3p) - lock a read-write lock for writing
pthread_rwlock_tryrdlock  (3p) - lock a read-write lock object for reading
pthread_rwlock_trywrlock  (3p) - lock a read-write lock object for writing
pthread_rwlock_unlock  (3p) - unlock a read-write lock object
pthread_rwlock_wrlock  (3p) - lock a read-write lock object for writing
pthreads  (7)         - POSIX threads
pthread_self  (3)     - obtain ID of the calling thread
pthread_setaffinity_np  (3) - set/get CPU affinity of a thread
pthread_setcancelstate  (3) - set cancelability state and type
pthread_setcanceltype  (3) - set cancelability state and type
pthread_setconcurrency  (3) - set/get the concurrency level
pthread_setname_np  (3) - set/get the name of a thread
pthread_setschedparam  (3) - set/get scheduling policy and parameters of a thread
pthread_setschedprio  (3) - set scheduling priority of a thread
pthread_setspecific  (3p) - thread-specific data management
pthread_sigmask  (3)  - examine and change mask of blocked signals
pthread_sigqueue  (3) - queue a signal and data to a thread
pthread_spin_destroy  (3p) - destroy or initialize a spin lock object (ADVANCED REALTIME THREADS)
pthread_spin_init  (3p) - destroy or initialize a spin lock object (ADVANCED REALTIME THREADS)
pthread_spin_lock  (3p) - lock a spin lock object (ADVANCED REALTIME THREADS)
pthread_spin_trylock  (3p) - lock a spin lock object (ADVANCED REALTIME THREADS)
pthread_spin_unlock  (3p) - unlock a spin lock object (ADVANCED REALTIME THREADS)
pthread_testcancel  (3) - request delivery of any pending cancellation request
pthread_timedjoin_np  (3) - try to join with a terminated thread
pthread_tryjoin_np  (3) - try to join with a terminated thread
pthread_yield  (3)    - yield the processor
vfs_aio_pthread  (8)  - implement async I/O in Samba vfs using a pthread pool

NPTL 源码
http://ftp.gnu.org/pub/gnu/glibc/glibc-2.9.tar.gz
或者
https://sourceforge.net/projects/nuttx/

2. 常用线程API介绍

2.1 创建线程 pthread_create

    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
    参数说明:
    thread :线程号  
    attr   :线程属性  
    (*start_routine) (void *) :线程运行函数的起始地址  
    arg :运行函数的参数

2.2 等待线程结束 pthread_join

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

        阻塞直到等待id为thread的线程退出,可以通过传出参数value_ptr获取线程退出状态,线程退出时  
    系统进行线程使用的资源的回收(如线程内部申请的动态内存、信号量等)。这个函数可以类比  
    进程中使用的wait, waitpid函数。  

    参数说明:
    thread : 线程号
    retval : 线程运行函数的返回值

2.3 互斥锁加锁 pthread_mutex_lock

    int pthread_mutex_lock(pthread_mutex_t *mutex);  
    int pthread_mutex_trylock(pthread_mutex_t *mutex);  

2.4 互斥锁解锁 pthread_mutex_unlock

    int pthread_mutex_unlock(pthread_mutex_t *mutex);

2.5 线程分离 pthread_detach

    int pthread_detach(pthread_t thread);

        线程分两种:joinable 或者 detach。对于POSIX线程,除非线程是被分离了的,否则在线程  
    退出时,它的资源是不会被释放的,需要调用pthread_join回收。  
        pthread_detach 函数使子线程主动与主线程断开关系,该子线程结束后其状态不能由其他线程  
    获取,而子线程自身自动释放资源,多用于网络、多线程服务器。  
    参数说明:
    thread : 线程号

2.6 线程退出 pthread_exit

    void pthread_exit(void *retval);

    线程可以隐式退出,也可以显式退出。
    参数说明:
    retval: 只要pthread_join中的第二个参数不是NULL,这个值将被传递给pthread_join函数  
    的第二个参数。

2.7 线程取消 pthread_cancel

    int pthread_cancel(pthread_t thread);

        功能是给线程发送取消信号,使线程从取消点退出。  
    该函数执行成功也不一定能取消掉指定线程的执行,因为这个函数线程执行函数进到内核时才会  
    被杀掉,如果用户一直运行在用户态不进到内核态也就无法取消线程的执行,此时可以使用  
    pthread_testcancel函数进到内核从而能够取消掉该线程的执行。  

        线程处于PTHREAD_CANCEL_ENABLE 状态,它就接受取消请求,如果线程处处于
    PTHREAD_CANCEL_DISABLE 状态,取消请求就会被保持在挂起状态。默认情况下,线程处于  
    PTHREAD_CANCEL_ENABLE状态。  

    根据POSIX标准,pthread_join()、pthread_testcancel()、pthread_cond_wait()、  
    pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会  
    引起阻塞的系统调用都是Cancelation-point,而其他pthread函数都不会引起Cancelation动作。  
    使用man -7 pthreads 查看取消点相关内容。  

    参数说明:
    thread : 要取消的线程id

2.7.1 线程取消涉及的内部属性

线程取消涉及的函数如下:

    设置取消状态:
    int pthread_setcancelstate(int state, int *oldstate);

    设置取消类型
    int pthread_setcanceltype(int type, int *oldtype);

        当线程将退出作为对取消请求的响应时,取消类型允许线程控制它在什么地方退出,包括:  
    PTHREAD_CANCEL_DEFERRED 时,线程只能在特定的几个取消点上响应取消请求,默认值  
    PTHREAD_CANCEL_ASYNCHRONOUS 时,线程在任何时候都可以响应取消请求  

2.8 线程条件处理发送信号 pthread_cond_signal

    pthread_cond_signal函数的作用是发送一个信号给另外一个正
在处于阻塞等待状态的线程,使其脱离阻塞状态,继续执行.如果没有线程处在阻塞等待状态, pthread_cond_signal也会成功返回。

    使用pthread_cond_signal不会有“惊群现象”产生,他最多只给
一个线程发信号。假如有多个线程正在阻塞等待着这个条件变量的话,那么是根据各等待线程优先级
的高低确定哪个线程接收到信号开始继续执行。如果各线程优先级相同,则根据等待时间的长短来确
定哪个线程获得信号。

    在LinuxThreads或者NPTL里面有两个队列,分别是cond_wait队
列和mutex_lock队列, cond_signal只是让线程从cond_wait队列移到mutex_lock队列,而不用
返回到用户空间,不会有性能的损耗。

    该函数对应pthread_cond_wait, 同类型函数
pthread_cond_broadcast。

    int pthread_cond_signal(pthread_cond_t *cond);

    参数说明:
    cond : 线程条件变量

2.9 线程条件处理广播信号 pthread_cond_broadcast

    int pthread_cond_broadcast(pthread_cond_t *cond);
    
    参数说明:
    cond : 线程条件变量

2.10 线程等待条件变量 pthread_cond_wait

    int pthread_cond_wait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex);

    线程等待处于挂起状态。为什么需要mutex见参考中列出的内容。  

    参数说明:
    cond :线程条件变量  
    mutex :互斥锁

    超时等待条件变量函数:
    int pthread_cond_timedwait(pthread_cond_t *restrict cond,
            pthread_mutex_t *restrict mutex,
            const struct timespec *restrict abstime);

    abstime 参数需要注意:  
    POSIX提供了多种时钟类型,其中包括以下两种:  
    CLOCK_REALTIME: Systemwide realtime clock. 系统范围内的实时时钟,是个软件时钟,  
        可以通过命令等方式修改该系统时间.
    CLOCK_MONOTONIC:Represents monotonic time. Cannot be set. 表示单调时间,为系统  
        起机时到现在的时间,不能被设置跟修改.

    pthread_cond_timedwait()在没有设置条件变量属性的时候,默认用的是CLOCK_REALTIME软件  
    时间,因此在极端情况下会出现实际等待的时间与设置的超时时间不同。

2.11 pthread_key_create

分配用于标识进程中线程特定数据的键。
    进程中并不能创建无限个的pthread_key_t变量。Linux中可以
通过PTHREAD_KEY_MAX(定义于limits.h文件中)或者系统调用sysconf(_SC_THREAD_KEYS_MAX)
来确定当前系统最多支持多少个键。Linux中默认是1024个键。

    查看pthread_key_create.c 源码实现文件,可以更好的理解
pthread_key_create 函数,里面用了个for循环,实际内部创建的是一个数组。

    int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));

    参数说明:
    key :线程特定数据的标识键  
    (*destructor)(void*) :线程结束时,系统将调用这个函数来释放绑定在这个键上的内存  

    对应的销毁函数
    int pthread_key_delete (pthread_key_t key);

2.12 设置线程数据共享 pthread_setspecific

设置变量value 与 pthread_key_t 类型的变量key进行关联。
pthread_getpecific和pthread_setspecific提供了在同一个线程中不同函数间共享数据即线程
存储的一种方法。
c++11 提供了一个新的数据类型 thread_local,该数据类型的变量在每个线程中都是一个副本,
进行修改等处理不影响其他线程内保存的该变量的值。

    int pthread_setspecific(pthread_key_t key, const void *value);

2.13 读取线程数据共享 pthread_getspecific

    void *pthread_getspecific(pthread_key_t key);

2.14 pthread_once

只执行1次的设置函数

       int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
       pthread_once_t once_control = PTHREAD_ONCE_INIT;

2.15 线程读写锁

       读锁:
       int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
       int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

       写锁:
       int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
       int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

       解锁:
       int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

3. 参考

POSIX 线程详解(经典必看)
https://www.cnblogs.com/sunminmin/p/4479952.html

GLIBC中NPTL线程实现代码阅读
https://blog.csdn.net/whuzm08/article/details/53537631

pthread_cond_wait 为什么需要传递 mutex 参数?
https://www.zhihu.com/question/24116967

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值