linux线程通信

一、线程
(1). 线程创建
    int pthread_create (pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
    第一个参数: thread:新线程的id,如果成功则新线程的id回填充到tidp指向的内存
    第二个参数: attr:线程属性(调度策略,继承性,分离性…)
    第三个参数: start_routine:回调函数(新线程要执行的函数)
    第四个参数: arg:回调函数的参数
    返回值: 成功返回0
    
    eq: int ret = pthread_create(&newTid, NULL, pthread_0, &arg);
    
    void* pthread_0(void *arg)
    {
        printf("newPthread:arg = %d\n", *(int *)arg);
        pthread_exit((void *)&val);
        return NULL;
    }
    
(2). 线程ID
    pthread_t tid = pthread_self();                 ---成功返回当前 线程ID
    
(3). 判断2个线程ID是否相等
    int pthread_equal (pthread_t tid1, pthread_t tid2);
    
(4). 线程退出
    1. 从启动函数中返回,返回值是线程的退出码。
    2. 线程可以被同一进程中的其他线程取消。
    3. 线程调用 pthread_exit() 函数。
        void pthread_exit(void *rval);
        参数:rval 是个无类型的指针,保存线程的退出码,其他线程可以通过 pthread_join() 函数来接收这个值。
        
(5). 线程回收,相当于进程的wait(), waitpid()
    1.线程的分离属性:
        分离一个正在运行的线程并不影响它,仅仅是通知当前系统该线程结束时,其所属的资源可以回收。
        一个没有被分离的线程在终止时会保留它的虚拟内存,包括他们的堆栈和其他系统资源,有时这种线程被称为僵尸线程(像没有回收的僵尸进程)。
        创建线程时默认是非分离的。

    2. int pthread_join(pthead_t tid, void **rval);
        功能:调用该函数的线程会一直阻塞,直到指定的线程 tid 调用 pthread_exit、从启动函数返回或者被取消。参数 rval 是指定线程的返回码, 如果线程被取消,那么 rval 被置为 PTHREAD_CANCELED.
        
    3. int pthread_detach(pthread_t thread);
        功能:分离一个线程,线程可以自己分离自己。那么当这个线程终止的时候,和它相关的系统资源将被自动释放。
        
(6). 线程取消
    1. int pthread_cancle(pthread_t tid);
        取消只是发送一个请求,并不意味着等待线程终止,而且发送成功也不意味着 tid 一定会终止,它通常需要被取消线程的配合。线程在很多时候会查看自己取消状态,如果有就主动退出, 这些查看是否有取消的地方称为取消点
        
    2.取消状态
        int pthread_setcancelstate(int state, int *oldstate);               
        参数:state 有两种值:PTHREAD_CANCEL_ENABLE(缺省,接收取消请求)和 PTHREAD_CANCEL_DISABLE(忽略取消请求)
        
    3.取消类型
        int pthread_setcanceltype(int type, int *oldtype) ;
        参数:type 由两种取值:PTHREAD_CANCEL_DEFFERED 表示收到信号后继续运行至下一个取消点再退出, PTHREAD_CANCEL_ASYCHRONOUS 标识立即执行取消动作(退出)
        
    4.取消点
        pthread_join()、 pthread_testcancel()、pthread_cond_wait()、 pthread_cond_timedwait()、sem_wait()、sigwait() 以及 write、read 等大多数会阻塞的系统调用。
        
(7). 线程清理
    void pthread_cleanup_push(void (*rtn)(void*), void *args)//注册处理程序
    void pthread_cleanup_pop(int excute)//清除处理程序
    线程可以安排它退出时的清理操作,这与进程的可以用atexit函数安排进程退出时需要调用的函数类似。这样的函数称为线程清理处理程序。线程可以建立多个清理处理程序,处理程序记录在栈中,所以这些处理程序执行的顺序与他们注册的顺序相反
    
    
    
二、线程的同步与互斥
1> 互斥量
(1). 互斥量初始化
    int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); //动态初始化互斥量
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //静态初始化互斥量

(2). 互斥量销毁
    int pthread_mutex_destroy(pthread_mutex_t *mutex); //动态互斥量销毁

(3). 加锁和解锁
    int pthread_mutex_lock(pthread_mutex_t *mutex);
    成功返回0,失败返回错误码。如果互斥量已经被锁住,那么会导致该线程阻塞。

    int pthread_mutex_trylock(pthread_mutex_t *mutex);
    成功返回0,失败返回错误码。如果互斥量已经被锁住,不会导致线程阻塞。
    
    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    成功返回0,失败返回错误码。如果一个互斥量没有被锁住,那么解锁就会出错。
    
(4). 死锁
    控制互斥量加锁的顺序来避免死锁,例如所有的线程都在加锁B之前先加锁A,那么这两个互斥量就不会产生死锁了。有的时候程序写的多了互斥量就难以把控,你可以先释放已经占有的锁,然后再加锁其他互斥量。

2> 信号量
    (1)同 进程通信 的信号量:sem_init(sem_t *sem, int pshared, unsigned int value), sem_wait(sem_t *sem), sem_post(sem_t *sem), int sem_destroy(sem_t *sem);
    不需要sem_open(), 和 sem_unlink();
    
3> 读写锁
    读写锁非常适合对数据结构读次数大于写次数的程序,当它以读模式锁住时,是以共享的方式锁住的(几个读锁可以同时操作);当它以写模式锁住时,是以独占的模式锁住的(只能一个写锁操作)。
(1). 读写锁的初始化和销毁
    int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
    const pthread_rwlockattr_t *restrict attr);
    int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

(2). 加锁和解锁
    (a).读模式加锁
    int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
    int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
    
    (b).写模式加锁
    int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
    int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
    
    (c).解锁
    int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

4> 条件变量
(1).条件变量的初始化和销毁
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //静态初始化条件变量
    int pthread_cond_init(pthread_cond_t *restrict cond,
    const pthread_condattr_t *restrict attr); //动态初始化条件变量
    int pthread_cond_destroy(pthread_cond_t *cond);//销毁条件变量

(2).条件变量的等待和唤醒
    int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
    int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
        这个函数与 pthread_cond_wait 类似,只是多一个 timeout,如果到了指定的时间条件还不满足,那么就返回。

    int pthread_cond_broadcast(pthread_cond_t *cond); //唤醒等待条件的所有线程
    int pthread_cond_signal(pthread_cond_t *cond); //至少唤醒等待条件的某一个线程

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值