zoukankan      html  css  js  c++  java
  • 线程基础--线程控制

    3.  线程控制

       1). 线程属性
         目标:能够设置 线程的 detached/join 状态。线程栈的大小和最低地址等属性。
         detached/join 状态的差别
         当线程处于 分离状态(detached)时,线程结束时。os马上回收资源。

    主线程不能够调用pthread_join获取线程退出时的返回值。

        当线程处于 未分离状态(join)时,线程结束时。主线程 调用pthread_join获取线程退出时的返回值, 随后释放该线程资源
            
         a)数据类型 pthread_attr_t
         b)初始化及释放属性结构 pthread_attr_init  pthread_attr_destroy 
            初始化时 会分配内存。所以一定要与 _..destroy 函数相相应
         c)获取或设置线程分离状态 pthread_attr_setdetachstate      pthread_attr_getdetachstate
           有2种可选的状态值:
           PTHREAD_CREATE_DETACHED   分离状态
           PTHREAD_CREATE_JOINABLE   正常状态,能够使用pthread_join来获取状态
         d)应该获取pthread_atr_destroy的返回值,由于使用pthread_attr_init初始化的时候可能分配有内存,假设释放内存失败的话,
           会造成内存泄漏
         e)控制线程栈的空间的大小
           需求:多个线程的栈空间累计超过了进程的可用虚拟地址空间
                 线程调用函数的自己主动变量非常多,或者递归非常深
           1)管理stackaddr线程属性。管理stacksize线程属性
           pthread_attr_getstack
           pthread_attr_setstack 
           2)获取或设置线程栈的大小
           pthread_attr_setstacksize  系统帮助分配内存,自己不用管
           pthread_attr_getstacksize
           3)线程栈的保护
           默认大小为宏PAGESIZE,但改动了栈属性后。这个值就会变成0
           pthread_attr_getguardsize
           pthread_attr_setguardsize
         f)线程属性-并发度
           pthread_attr_setconcurency
           pthread_attr_getconcurency
     
       2). 同步属性 (线程的同步对象 (例:相互排斥量、读写锁、条件变量)的属性)
          实现同步的3种方式中的对象的属性
         a)相互排斥量属性 pthread_mutexattr_t
           1)初始化及释放  pthread_mutexattr_init pthread_mutexattr_destroy
           2)进程共享属性
             获取与设置共享属性 pthread_mutexattr_getpshared   pthread_mutexattr_setpshared
             PTHREAD_PROCESS_PRIVAE 进程内的多个线程能够訪问同一个同步对象,默认属性
             PTHREAD_PROCESS_SHARED 多个进程能够共享同一块内存区域  内存共享技术。

    将相互排斥量用于进程间对同一内存区訪问的同步

              
           3)相互排斥量类型属性
             目标:设置 同一线程对已上锁的相互排斥量再次上锁 是否 死锁等属性。

             PTHREAD_MUTEX_NORMAL   标准的相互排斥量类型。不做错误检查或死锁检查
             PTHREAD_MUTEX_DEFAULT  依赖于操作系统提供到其它类型的映射
             PTHREAD_MUTEX_ERRORCHECK 提供错误检查
             PTHREAD_MUTEX_RECURSIVE (递归锁)同意多次加锁,可是须要解锁相应次数 tmd,这个类型叫做递归锁
             获取与设置相互排斥量类型属性
             pthread_mutexattr_gettype  pthread_mutexattr_settype
         应用场景
         PTHREAD_MUTEX_RECURSIVE (递归锁) 当将现有的单线程接口放到多线程环境中时。使用递归锁
         例:
         
         
          同一线程中 func1、 func2分别对 相互排斥量加锁, 若不是用 递归锁则会出现死锁。
        
     
         b)读写锁属性 pthread_rwlockattr_t
            能够设置是否支持进程共享属性 (默觉得 仅仅支持 线程共享属性 )

         c)条件变量属性pthread_condattr_t
            能够设置是否支持进程共享属性 (默觉得 仅仅支持 线程共享属性 )
     
    4. 线程重入
         可重入函数--指在信号处理函数中。正在执行的程序被信号处理程序中断后,返回时 不能正确执行的函数。
        原因:(a)使用了静态数据结构--全局的,会被其它线程/信号处理函数 等 使用
         (b)调用了 malloc / free ( malloc 为它所分配的存储区维护一个链接表,运行信号处理函数时,进程可能正在改动
              该表,导致被破环)
        (c)标准I/O函数--大部分使用了 全局结构变量

         1)线程安全:假设一个函数同一时刻能够被多个线程安全地调用
         2)系统是否支持线程安全函数  sysconf(_POSIX_THREAD_SAFE_FUNCTIONS)
         非线程安全的原因:返回的数据存放在静态的内存缓存区。多个线程调用该函数的时候 会覆盖前面正在使用的区域。

         将其进行可重入,为其分配自己的缓存器。避免被其它线程干扰,能够保证是线程安全的。
         重入后的函数,成为线程安全,并不意味着 它对信号处理程序是可重入的。

    (请举例,不太懂??)


         3)异步-信号安全:假设函数对异步信号处理程序的重入是安全的
         4)锁文件的3个函数
           flockfile  ftrylockfile   funlockfile
           该锁是递归锁
         5)确保函数在进程里面仅仅被调用一次
           pthread_once_t var = PTHREAD_ONCE_INIT;
           pthread_once(&var, function);
     
    5. 线程私有数据
         一种 让存储和查询 数据 与 某个线程相关的 机制。避免 与其它线程 同步訪问的问题
         1)须要的数据类型: pthread_key_t
         2)创建私有数据的步骤
            pthread_key_t key;     
           a)pthread_key_create(&key, 清理函数地址) 一般通过pthread_once确保函数仅仅被运行一次。变量仅仅被初始化一次
           b)char* addr = pthread_getspecific(&key)
           c)为addr分配内存 malloc
           d)pthread_setspecific(&key, addr);
           e)pthread_key_delete删除key
           f)线程退出。运行清理函数地址
     
    6.  线程取消
         设置pthread_cancle 函数相关的属性项
         1)线程能够被设置为是否可取消
           pthread_setcancelstate(int state, int* oldstate)
         2)pthread_cancel仅仅是一个申请,仅仅有线程到达了取消点才会取消.
         3)延迟取消pthread_testcancel, 适合于没有取消点的函数
         4)设置取消的类型pthread_setcanceltype
     
    7.  线程与IO
         pread,pwrite 原子io操作
        例:
        线程A 
        lseek( fd, 300, SEEK_SET);
        read( fd, buf1, 100);
        线程B
        lseek( fd, 700, SEEK_SET);
        read( fd, buf2, 100);
        当 A运行完lseek,B在A调用read之前调用lseek, 最后 两线程 读取同一条记录 (对同一文件操作,后一个 偏移量设置 覆盖了前一个设置)。
        解决方法:
        pread--将偏移量设定和数据读取成为一个原子操作
        线程A
        pread( fd, buf1, 100, 300);
        线程B
        pread( fd, buf2, 100, 700);

    8.  线程与信号
     
        每一个线程有自己的信号屏蔽字。可是他们共享 
        1)同样的信号处理函数 2)该信号与某函数的绑定,一个信号绑定到某个函数,这个被全部线程共享, 他们仅仅能看到一个
        多个线程公用进程的信号屏蔽机制。除了2种情况以外:
        硬件故障的信号与计时器超时的信号,仅仅递送给某个线程。其他的信号会发送给全部线程
        pthread_sigmask
        sigwait 等待信号发送.  一般操作须要先堵塞信号,sigwait调用会取消信号的堵塞状态,直到新信号到来
        pthread_kill
        sigwait(sigset_t*, int* signo)
        sigwait的參数2表示捕获到的信号值
     
    9.  线程与fork
        pthread_atfork,理论内容相当多,过滤掉
        当线程调用fork时。就会为子进程创建整个进程空间的副本。包含从父进程继承的相互排斥量、读写锁和条件变量等。
        因此,假设父进程包括多个线程。子进程在fork返回后。没有调用exec (原来的地址空间会被丢弃)的话。就须要清理锁状态。
        pthread_atfork( void (*prepare)(void), void (*parent)(void),void (*child)(void));
        能够设置3个锁清理函数。

     

        prepare fork 由父进程 在fork创建子进程前调用。任务:获取父进程定义的全部锁。
        parent fork: fork创建子进程后,但在fork返回之前,在父进程中 调用。
        child fork :fork创建子进程后。但在fork返回之前。在子进程中 调用。
     
    10.  同一进程的全部线程共享同一个计时器

    11.  同一进程的全部线程共享同样的文件描写叙述符
  • 相关阅读:
    洛谷P1120信息奥赛一本通1442 小木棍
    洛谷P1378 油滴扩展
    洛谷P1156 垃圾陷阱
    mybatis-Plus 实践篇之逆向工程
    Interceptor的使用及探究
    mysql,oracle,sqlServer 元数据查询
    navicat premium15免费版安装说明(附工具)
    打印日志你真的会吗?
    线程基础知识-必知必会
    空间复杂度&时间复杂度
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6905522.html
Copyright © 2011-2022 走看看