系统编程——线程学习笔记

守护进程:
    daemon进程,通常运行于操作系统后台,脱离控制终端。一般不与用户直接交互。
    周期性的等待某个事件发生或周期性执行某一动作。
    不受用户登录注销影响,通常采用以d结尾的命名方式

守护进程创建步骤:
    1、fork子进程,让父进程终止
    2、子进程调用setsid()创建新会话
    3、通常根据需要,改变工作目录位置chdir()  (防止目录被卸载)
    4、通常根据需要,重设umask文件权限掩码        (影响新文件的创建权限)
    5、通常根据需要,关闭/重定向 文件描述符
    6、守护进程 业务逻辑。while()

线程概念:
    进程:有独立的 进程地址空间,有独立的pcb。        分配资源的最小单位
    线程:有独立的pcb,没有独立的进程地址空间。
    ps -Lf 进程Id  ---->线程号。LWP --->cpu执行的最小单位。
    
线程共享:
    独享 栈空间(内核栈、用户栈)
    共享./text./data ./rodata ./bass heap  -->全局变量

线程控制原语:
    pthread_t pthread_self(void); 
        获取线程id。线程id是在进程地址空间内部,用来标识线程身份的id号
        返回值:本线程 id
    
    检查出错返回:线程当中用
        fprintf(stderr,"xxxxxx %s\n", strerror(ret));
        
    pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_rountn)(void*), void *arg);
        参数1:传出参数,表新创建的子线程id
        参数2:线程属性,传NULL表使用默认属性
        参数3:子线程回调函数,创建成功,pthread_create函数返回时,该函数会被自动调用
        参数4:参3的参数,没有的话,传NULL
    返回值:
        成功:0
        失败:errno
    
    循环创建N个子线程:
        for(i=0;i<5;i++)
            pthread_create(&tid, NULL, tfn, (void*)i); //将int类型i,强转成void*,传参
    
    void pthread_exit(void* retval); 退出当前线程
        retval:退出值,无退出值时,NULL
        
        exit():退出当前进程
        return:返回到调用者那里去
        pthread_exit():退出当前线程
    int pthread_jion(pthread_t thread, void **retval); //回收线程
        thread:待回收的线程iD
        retval:传出参数,回收的那个线程的退出值
        返回值:
            成功:0
            失败:errno
    int pthread_detach(pthread_t thread)    //设置线程分离
        thread:待分离的线程id
        返回值:    
            成功:0
            失败:errno
    int pthread_cancel(pthread_t thread);//杀死一个线程,需要到达取消点(保存点)
        thread:待杀死的线程id
        返回值:    
            成功:0
            失败:errno
        如果,子线程没有到达取消点,那么pthread_cancel无效
        我们可以在线程中,手动添加一个取消点,使用pthread_testcancel();
        成功被pthread_cancel 杀死的线程,返回 -1, 使用pthread_join回收

        线程控制原语:        进程控制原语
        pthread_create        ->fork()
        pthread_self        ->getpid()
        pthread_exit()        ->exit() 
        pthread_join()        ->wait/waitpid()
        pthread_cancel()    ->kill()
        pthread_detach()    
线程属性:
    设置分离属性:
    pthread_attr_t attr        创建一个线程属性结构体变量
    pthread_attr_init(&attr)    初始化线程属性
    pthread_attr_setdatachstate(&attr,     PTHREAD_CARETE_DETACH);//设置线程属性为分离态
    pthread_carete(&tid, &attr, tfn, NULL) 借助修改的,设置线程属性 创建为分离态的新线程
    pthread_attr_destory(&attr)    销毁线程属性

线程同步:
    协同步调,对公共区域数据按序访问,防止数据混乱,产生于时间有关的错误。

锁的使用:
    建议锁!对公共数据进行保护。所有线程【应该】在访问公共数据前先拿锁再访问,但 锁本身不具备强制性
使用mutex(互斥锁、互斥量)一般步骤:
    1、pthread_mutex_lock:创建锁
    2、pthread_mutex_init:初始化
    3、pthread_mutex_lock:加锁
    4、访问共享数据
    5、pthread_mutex_unlock:解锁
    6、pthread_mutex_destroy:销毁锁
    
    初始化互斥量:
        pthread_mutex_t mutex;
        1、pthread_mutex_init(&mutex, NULL)        动态初始化
        2、pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER  静态初始化
        
    注意事项:
        尽量保证锁的粒度,越小越好。(访问共享数据前,加锁;访问结束后【立即】解锁)
        互斥锁,本质是结构体。我们可以看成整数。初值为1(pthread_mutex_init()函数调用成功)
        加锁:--操作,阻塞线程
        解锁:++操作,唤醒阻塞在锁上的线程
        try锁:尝试加锁,成功--。失败,返回。同时设置错误号EBUSY

restrict关键字:
    用来限定指针变量,被该关键字限定的指针变量所指向的内存操作,必须由本指针完成

【死锁】:
    是使用锁不恰当导致的现象:
        1、对一个锁反复lock
        2、两个线程,各自持有一把锁,请求另一把
读写锁:
    锁只有一把,            以读方式给数据加锁--读锁。以写方式给数据加锁==写锁
    读共享,写独占
    写锁优先级高
    相较于互斥量而言,当读线程多的时候,提高访问效率。
    pthread_rwlock_t rwlock;
    pthread_rwlock_init(&rwlock, NULL);
    pthread_rwlock_rdlock
    pthread_rwlock_wrlock
    pthread_rwlock_unlock
    pthread_rwlock_destroy

条件变量:
    本身不是锁!但是通常结合锁来使用(mutex)
    pthread_cond_t cond;
    初始化条件变量:
        1、pthread_cond_init(&cond, NULL); 动态初始化
        2、pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 静态初始化
    阻塞等待条件:
        pthread_cond_wait(&cond, &mutex);
        作用:
            1)阻塞等待条件变量满足
            2)解锁已经加锁成功的信号量(相当于pthread_mutex_unlock(&mutex))
            3)当条件满足,函数返回时,重新加锁信号量(相当于pthread_mutex_lock(&mutex))
            
    pthread_cond_signal():唤醒阻塞在条件变量上的(至少)一个线程
    pthread_cond_broadcast():唤醒阻塞在条件变量上的所有线程
    【要求:能够借助条件变量,完成生产者消费者问题】

信号量:        
    应用于线程、进程间同步
    相当于 初始化值为N的互斥量。N值 表示可以同时访问共享数据区的线程数
    函数:
        sem_t sem;    定义类型
        int sem_init(sem_t *sem, int pshared, unsigned int value)
        参数:
            sem:信号量
            pshared:0:用于线程间同步
                     1:用于进程间同步
            value:N值(指定同时访问的线程数)
    sem_destroy();
    sem_wait()        一次调用,做一次--操作,当信号量的值为0时,再次--就会阻塞。(对比pthread_mutex_lock)
    sem_post()        一次调用,做一次++操作,当信号量的值为N是,再次++就会阻塞。(对比pthread_mutex_unlock)
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值