zoukankan      html  css  js  c++  java
  • linux 下的多线程编程

    Linux 下POSIX线程 

    使用threadid标识一个线程。

    创建线程的函数如下:

       1: #include <pthread.h>
       2:  
       3: int pthread_create(
       4:        pthread_t *restrict tidp,
       5:        const pthread_attr_t *restrict attr,
       6:        void *(*start_rtn)(void *), void *restrict arg);

     

    判断两个线程是否相同

       1: #include <pthread.h>
       2:  
       3: int pthread_equal(pthread_t tid1, pthread_t tid2)

    获取本线程的线程id

       1: #include <pthread.h>
       2:  
       3: pthread _t pthread_self(void);

    线程终止

       1: #include <pthread.h>
       2:  
       3: void pthread_exit(void *rval_ptr);
       4:  
       5: int pthread_join(pthread_t thread, void **rval_ptr);

    一个线程可以要求另外一个线程被终止:

       1: #include <pthread.h>
       2:  
       3: void pthread_cancel(pthread_t tid)

    线程cacel的取消由state和type决定。相关函数如下:

       1: #include <pthread.h>
       2:      int pthread_setcancelstate(int state, int *oldstate);
       3:  
       4:      int pthread_setcanceltype(int type, int *oldtype);
       5:  
       6:      void pthread_testcancel(void);

    pthread_setcancelstate 原子的设置线程的state,并返回之前的状态(oldstate)。可能取值为:PTHREAD_CANCEL_ENABLE 和 PTHREAD_CANCEL_DISABLE

    pthread_setcanceltype 原子的设置线程的type,并返回之前的type。可能的取值为:PTHREAD_CANCEL_DEFERRED 和 PTHREAD_CANCEL_ASYNCHRONOUS

    新创建的线程的state和type默认分别为PTHREAD_CANCEL_ENABLE 和 PTHREAD_CANCEL_DEFERRED

    这些属性需要再开始设置,而不能在线程运行中修改。

     

       1: #include <pthread.h>
       2:  
       3: void pthread_cleanup_push(void (*rtn)(void *), void *arg);
       4: void pthread_cleanup_pop(int execute);

    这两个函数维护一个函数指针的Stack,可以把函数指针和函数参数值push/pop。执行的顺序则是从栈顶到栈底,也就是和push的顺序相反。

    在下面情况下pthread_cleanup_push所指定的thread cleanup handlers会被调用:

    a. 调用pthread_exit

    b. 相应cancel请求

    c. 以非0参数调用pthread_cleanup_pop()。(如果以0调用pthread_cleanup_pop(),那么handler不会被调用

    有一个比较怪异的要求是,由于这两个函数可能由宏的方式来实现,因此这两个函数的调用必须得是在同一个Scope之中,并且配对,因为在pthread_cleanup_push的实现中可能有一个{,而pthread_cleanup_pop可能有一个}。因此,一般情况下,这两个函数是用于处理意外情况用的,举例如下:

       1: void *thread_func(void *arg)
       2: {
       3:     pthread_cleanup_push(cleanup, “handler”)
       4:  
       5:     // do something
       6:  
       7:     Pthread_cleanup_pop(0);
       8:     return((void *)0);
       9: }

    注: 个人测试,pthread_cleanup_push 和pthread_cleanup_pop的个数也要一致。

     

    线程同步

    互斥量Mutex

    同一时刻只能有一个线程拿到锁

    创建和关闭的方法:

       1: #include <pthread.h>
       2:  
       3: int pthread_mutex_init(
       4:        pthread_mutex_t *restrict mutex,
       5:        const pthread_mutexattr_t *restrict attr)
       6:  
       7: int pthread_mutex_destroy(pthread_mutex_t *mutex);

    加锁解锁的方法:

       1: #include <pthread.h>
       2:  
       3: int pthread_mutex_lock(pthread_mutex_t *mutex);
       4:  
       5: int pthread_mutex_trylock(pthread_mutex_t *mutex);
       6:  
       7: int pthread_mutex_unlock(pthread_mutex_t *mutex);

     

    读写锁

    读写锁有三种状态

    i. 一个或者多个线程获得读锁,其他线程无法获得写锁

    ii. 一个线程获得写锁,其他线程无法获得读锁

    iii. 没有线程获得此读写锁

     

    创建和关闭的办法

       1: #include <pthread.h>
       2:  
       3: int pthread_rwlock_init(
       4:        pthread_rwlock_t *restrict rwlock,
       5:        const pthread_rwlockattr_t *restrict attr)
       6:  
       7: int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

     

    加锁解锁的办法:

       1: #include <pthread.h>
       2:  
       3: int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
       4:  
       5: int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
       6:  
       7: int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
       8:  
       9: int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
      10:  
      11: int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

     

    Conditional Variable

    条件变量是使得线程等待在一个条件上,直到其他的线程触发条件满足。

    条件必须被Mutex保护起来

    b. 类型为:pthread_cond_t,必须被初始化为PTHREAD_COND_INITIALIZER(用于静态分配的条件,等价于pthread_cond_init(…, NULL))或者调用pthread_cond_init

    创建和销毁的办法:

       1: #include <pthread.h>
       2:  
       3: int pthread_cond_init(
       4:        pthread_cond_t *restrict cond,
       5:        const pthread_condxattr_t *restrict attr)
       6:  
       7: int pthread_cond_destroy(pthread_cond_t *cond);

    等待条件发生的方法:

       1: #include <pthread.h>
       2:  
       3: int pthread_cond_wait(
       4:        pthread_cond_t *restrict cond,
       5:        pthread_mutex_t *restrict mutex);
       6:  
       7: int pthread_cond_timedwait(
       8:        pthread_cond_t *restrict cond,
       9:        pthread_mutex_t *restrict mutex,
      10:        const struct timespec *restrict timeout);

    pthread_cond_wait函数用于等待条件发生(=true)。pthread_cond_timedwait类似,只是当等待超时的时候返回一个错误值ETIMEDOUT。超时的时间用timespec结构指定。此外,两个函数都需要传入一个Mutex用于保护条件

    等待时间的结构:

       1: struct timespec {
       2:        time_t tv_sec;       /* seconds */
       3:        long   tv_nsec;      /* nanoseconds */
       4: };

    注意timespec的时间是绝对时间而非相对时间,因此需要先调用gettimeofday函数获得当前时间,再转换成timespec结构,加上偏移量。

     

    通知条件满足的函数:

       1: #include <pthread.h>
       2:  
       3: int pthread_cond_signal(pthread_cond_t *cond);
       4:  
       5: int pthread_cond_broadcast(pthread_cond_t *cond);

    两者的区别是前者会唤醒单个线程,而后者会唤醒多个线程。

     

     

    refer:Linux Thread 介绍总结

    http://www.cnblogs.com/zhenjing/archive/2010/12/27/cancel_thread.html

  • 相关阅读:
    poj-1069(三角形和六边形)(转)
    poj-1024(唯一最短路径)(转)
    poj-1022(四维模仿)(转)
    poj-1020(填蛋糕)(转)
    poj-1011
    poj-1010(转)
    poj-2312
    nyoj--幸运三角形
    nyoj--Divideing Jewels
    关于 APP在接入flutter之后在多任务下看不到AppName,只有APP图标,正常应该是APP图标+APP名称
  • 原文地址:https://www.cnblogs.com/lovemdx/p/3288392.html
Copyright © 2011-2022 走看看