锁小结

<锁用来保护的是数据而非代码>(程序员的自我修养)

同步与互斥:
     同步:对多个相关进程在执行次序上进行协调,使并发指向的诸进程之间能按照一定的规则共享系统资源,并能很好的相互合作,从而来保证程序的执行可再现性
     互斥:一个时间段内,只能有一个进程访问这个资源,资源的排他性。区别与同步,诸进程间可以无序访问

     信号量和互斥锁的区别:
          <1>互斥量值只能为0/1,信号量值可以为非负整数(一个信号量封锁的区域,可以允许多个进程进入)
          <2>互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到

    为什么提供锁:硬件底层没有提供这样一种的原子操作:检测--赋值。 我所知道的三种手段:新提供的硬件原子指令, 关中断, 总线封锁
    忙等待 空闲等待  是否形成队列
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  锁:OS中描述的互斥手段:
     硬件同步机制:忙等
          关中断:关中断不适用于多核处理器,一个cpu上关中断,不能防止进程在另一个处理器上访问共享变量-----自旋锁
          利用test-and-set指令互斥
          利用swap指令实现进程的互斥   XCHG      
    信号量机制:
          整型信号量         忙等
          记录型信号量     等待队列    block使进程阻塞  wakeup唤醒进程  多个进程共享一个临界资源 
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
自旋锁(常规自旋锁,读写锁)spinlock 忙等待   (锁的粒度?)
    自旋锁--适用于执行量少的代码,减少上下文切换  
    读写锁:可以多个线程进入读操作,但只允许一个线程进行写操作。不允许递归,一个时刻只能一个线程持有该锁

     自旋锁在单处理器不可抢占条件下什么也不做
     自旋锁在单处理器可抢占条件下禁止中断
     自旋锁在多处理器下对总线进行封锁,获得自旋锁才能去访问总线
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一般情况下的线程间的同步方式:
信号量(信号量,使用者数量的不同:互斥信号量、计数型信号量,读写信号量) (信号量有两种,sem_init , sem_wait, sem_post, sem_destroy, semop, semctl, sem)         具有阻塞和非阻塞两种
 如果有使用锁的,保存现场进入睡眠,将自己插入等待队列,如果锁释放就会唤醒该进程,需要进行现场保护恢复等操作
 信号量不同于自旋锁,不会禁止内核抢占,所以持有信号量的代码可以被抢占
 信号量可以同时允许任意数量的锁持有者,而自旋锁一个时刻只能一个任务持有
 当获取不成功的时候,任务会将自身放入一个队列中睡眠,指导信号量被释放才唤醒下一个进程,必须在能睡眠的进程中使用。

互斥量: Linux高性能服务器编程中,互斥锁提供了一套属性设置,通过设置属性提供了四种不同的锁
   1> 同信号量一样,资源仅同时允许一个线程访问,但和信号量不同的是,信号量在整个系统中可以被任意的线程获取并释放,即同一信号量可以被系统中的一个线程获取之后由另一个线程释放,而互斥量则要求那个线程获取到了互斥量,那个线程要负责释放这个锁,其它线程去释放是无效的
  2>互斥量也是有属性设置的,可以实现进程间的共享,但是要看具体的操作系统是否支持
  3>如果是普通互斥锁,对已经加锁的互斥锁再次加锁会引起死锁

条件变量: 如果说互斥锁是用于同步线程对共享数据的访问的话,那么条件变量则是用于在线程之间同步共享数据的值。条件变量提供了一种线程间的通知机制:当某个共享数据达到某个值的时候,唤醒等待这个共享数据的线程。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
自旋锁spinlock:底下分为四种,分别是普通锁,关闭硬中断(是否保存现场),软中断等来实现。
    1>自旋锁底下支持读写锁,读的时候可以多个线程获得锁,写的时候只能一个任务获得该锁
    2>没有获得该锁的线程处于忙等待,所以使用该锁的代码要少
    3>在获取该锁的时候不能有改变进程状态的代码,否则该进程的状态改变需要等待
    4>在单处理器上,如果操作系统允许抢占那自旋锁就相当于禁止抢占,否则自旋锁相当于没有。在多处理器上自旋锁只能禁止一个处理器上的中断,但是不能保证该任务在别的处理器上运行。
    5>不能在一段代码下连续两次获得自旋锁。否则将陷于死锁状态

互斥量: 同信号量一样,资源仅同时允许一个线程访问,但和信号量不同的是,信号量在整个系统中可以被任意的线程获取并释放,即同一信号量可以被系统中的一个线程获取之后由另一个线程释放,而互斥量则要求那个线程获取到了互斥量,那个线程要负责释放这个锁,其它线程去释放是无效的
    1>同信号量,将等待进程加入队列,在linux下线程和进程的区别不是很明显,用户线程和内核线程是一对一的,所以由操作系统来调度线程,所以在加入等待队列后,由操作系统进程唤醒
    2>信号量具有死锁的风险
    3>同自旋锁比较,自旋锁用于上下文切换的操作比较少,但是互斥量要进行保护恢复等操作,所以在等待时间较短的情况下使用自旋锁,等待时间较长的情况下使用互斥量


信号量:semphere Dijistra v进化之路漫长
    1>记录型型号量,信号量集。刚开始的信号量要使用忙等待,后来在记录型信号量中,,直到
    2>信号量:通过设置属性,可以达到进程之间线程之间的同步工作
     int sem_init(sem_t *sem, int pshared, unsined value);//通过设置pshared来控制是当前进程的局部信号量还是多个进程之间共享的
    3>信号量区别互斥量的地方,互斥量相当于信号互斥量,只能允许加锁,解锁对一个资源的同步, 但是信号量可以允许对多个资源的同步互斥
   《信号量的底层使用到自旋锁,禁止中断以及保护现场,在未获得锁的过程中,未获得锁的进程设置timeout插入等待队列进行睡眠schedule_timeout(timeout),进行睡眠,在timeout之后 醒来进行检测锁是否释放,锁的释放通过schedule进行调度。否则继续睡眠》

你可能感兴趣的:(Linux编程)