APUE笔记 线程

概念

一个线程拥有表示线程执行环境的信息:

线程id

一组寄存器值,栈,

信号屏蔽字,

errno变量

线程私有变量

进程的所有信息对线程共享

代码段,栈,堆,文件描述符!

线程测试宏_POSIX_THREADS



线程标识

线程用线程id标识,pthread_t

pthead_t,在不同系统中看实现而定,so可能是结构体,为确保可移植性,最好不要当整数来处理

so比较时,用pthread_equal函数比较是否相等

#include<pthread.h>

int pthread_equal(pthread_t p1, pthread_t p2);//相等返回!0, 不等返回0


#include <pthread.h>

pthread_t pthread_self(void);//返回想线程自身id


线程只在进程上下文中才有效!


线程创建

#include<pthread.h>

int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void * (*fun)(void *), void arg);//成功返回0,错误返回函数返回的错误码

创建的id通过 tid返回,可能在create返回前,指定的函数就执行,so不要在执行函数中用共享的进程中的tid取当前进程值

attr 指定线程的类型

fun 指定的函数的执行起始地址

arg,向fun传递参数是,将 参数保存在结构体,fun通过arg传递的地址取相应参数的值


新线程继承调用线程的浮点环境和,屏蔽信号字,但挂起信号被擦出

信号在创建是要休眠,否则,主线从退出,进程就会退出!


写读,写写

一般的写的存储器周期,可能比读存储器周期长,读写同时进行,可能会导致周期交叉,导致数据出错


互斥量

当对某偶一个,互斥量加锁时,其他欲锁此变量的线程被阻塞

当一个线程释放互斥量时,所有阻塞线程变为可运行状态,第一个为可运行的线程可加锁,运行其他依旧阻塞

同步只对加锁的线程有效,其他无锁可访问的线程也会导致一致性


#include<pthread.h>

int pthread_mutex_init(pthread_mutext_t *mutex, const pthread_mutex_attr *restrict attr);//成功返回0,否则返回错误码

int pthread_mutex_destory(ptread_mutex *mutex);//成功返回0,否则返回错误码

使用mutex之前必须初始化!

动态初试话mutex(使用malloc),attr 为NULL使用默认初始化

so必须使用pthread_mutex_destory 配对销毁信号量

可以用PTHREAD_MUTEX_INITIALIZER静态初始化mutex


#include<pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutx);//已经被锁,阻塞线程,成功返回0,否则返回错误码

int pthread_mutex_trylock(pthread_mutex_t *mutx);//mutex已经被锁,直接返回EBUSY,不希望线程被阻塞用此锁

int pthread_unlock(pthread_mutex_t *mutx);//解锁互斥量


死锁避免

当出现多个线程一相反的顺序锁住互斥量时,很可能会发生死锁

so使各个线程以相同的顺序锁住互斥量,避免死锁


有时因为程序结构,对互斥量排序比较困难

可以采用pthread_mutex_terylock,当锁住第一个mutex时才继续前进,否则释放获得的锁,一段时间再试!


锁的粒度是一个需要考虑的问题,若粒太大,则可能串行等待,不能很好并发

太细,加锁解锁耗时,编程复杂度大!

pthread_mutex_timedlock

设置绝对时间,阻塞到指定时间(过了呢?实验!)


读写锁

读写锁可以理解为共享互斥锁!相对互斥量,一次只能一个线程持有处理,并发性更好!

加读锁时,其它线程能加读锁,不能加写锁(被阻塞)-------共享方式加读锁

加写锁时,其他不能加读锁也不能加写锁(被阻塞)--------互斥方式加写锁

一般系统实现时,在申请写锁后会阻塞线程读锁的请求,以防止大量的读操作时写锁一直不能获得!(适用于读操作远大于写操作情况)


初始化

#include<pthread.h>

int pthread_init(pthread_rwlock_t *rwlock, const pthread_rwlock_attr_t *restrict attr);

若使用默认参数,attr设为NULL!

int pthread_destory(pthread_rwlock_t rwlock);

成功返回0 ,失败返回错误编号


如果在线程持有锁时,释放锁,会导致不可预知的结果!

信号量必须用destory函数销毁,进行资源回收,才能释放内存,否则会是的资源泄漏(锁相关资源,具体待查!)

也可以使用PTHREAD_RWLOCK_INITIALIZER静态初始化!


加锁解锁

#include<pthread.h>

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//加读锁

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//加写锁

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解读/写 锁

成功返回0,否则错误编号

不阻塞加锁

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);//加读锁

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);//加写锁

成功返回0,否则返回EBUSY


超时的读写锁


条件变量

条件变量,wait使用一方,等待signal产生信号是才能继续执行

wait将当前线程放入等待队列阻塞,当siagnal时唤醒继续执行

signal,唤醒等待队列的线程,若无等待队列则信号不保存(放空炮)


#include <pthread.h>

pthread_cond_wait(pthread_cond_t *cndnd, pthread_mutex_t *mutex);

等待之前必须锁住mutex,在之后语句中unlock  mutex!(1)

wait在将线程放如等待队列之后unlock mutex ,使得不至于当前线程在未进入等待队列之前,就产生产品,而队列中无等待者,使得等待线程永久等待!

在wait返回后会lock mutex,接下来的(1)unlock生效!

在等待之前一定要判断等待条件,

有产品则不等待,防止生产者先执行,signal次数不够,因为signal信号不会累加!

若无产品,则直接等待signal唤醒即可

在唤醒后,可直接操作产品,因为接下来的语句都是在获得了mutex之后的不会冲突                                    

int pthread_cond_signal(pthread_cond_t *cond);

唤醒一个线程

一定要在生产完之后才能signal

生产时一定要mutex

int pthread_cond_signal(pthread_cond_t *cond);

唤醒所有线程


#include <iostream>
#include <pthread.h>

using namespace std;


pthread_mutex_t mutex;
pthread_cond_t cond;

 pthread_t tid1,tid2 ,tid3;
int flag = 0;
void* fun(void *)
{
    for(int i = 0; i < 2; i++)
    {

    pthread_mutex_lock(&mutex);

    cout << "thread==>"<<pthread_self()<<"waiting"<<endl;    
    while(flag <= 0)pthread_cond_wait(&cond, &mutex);//有产品则不等待,无产品则等待唤醒,等待时释放锁
                                                                                                                    //到此wait退出前 加锁mutex
     cout << "thread==>"<<pthread_self()<<endl;
     flag --;
    pthread_mutex_unlock(&mutex);

    cout << "thread==>"<<pthread_self()<<"out=>"<<i<<endl;

    }
    return (void *)0;
}

void *creator(void *)
{
    for(int i = 0; i < 4; i++)
    {

    pthread_mutex_lock(&mutex);
    flag ++;//记录产品数

    pthread_cond_signal(&cond);

    pthread_mutex_unlock(&mutex);

    }

    cout << "creator created 4 signal"<<endl;
}


int main()
{

    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond, NULL);
    
    pthread_create(&tid1, NULL,creator, NULL);
    pthread_create(&tid2, NULL,fun, NULL);
    pthread_create(&tid3, NULL,fun, NULL);
    
   sleep(10);
    cout << "Hello world!" << endl;
    return 0;
}




屏障

使得指定数量的线程都到达某一指定点时,所有线程才能继续执行,否则等待

# include <pthread.h>

int phread_barrier_init(pthread_barrier *restrict barrier, const pthread_barrierattr_t *restrict attr, int count);

当count数量的到达时才能继续 执行

int phread_barrier_destory(pthread_barrier *barrier);

成功返回0,否则错误编码

int pthread_barrier_wait(pthread_barrier *barrier);

表示本线程已经到达等待点,等其他线程干上来

barrier在所有线程都赶上后,可重用,但必须现destory再 init,保证count值












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值