Lock 锁

Published: 21 Sep 2015 Category: tech

一、锁的种类有以下几种:

1.按用途分,门锁可以分为户门锁、卧室锁、浴室锁和通道锁。

(1)户门锁:安在住宅的入户门上,因此,户门锁必须是防盗锁,它的安全性是第一位的。因为入户门外通常加装防盗门,两者之间的空隙比较小,所以户门锁通常选用不带把手的弹簧锁(俗称“呆锁”),以免锁的把手顶到防盗门上,关不上门。
(2)卧室锁:安在各个卧室的门上,必须能保证卧室的私密性。能在里面锁上,外面开启必须用钥匙。
(3)浴室锁:安在卫生间或浴室,能在里面锁住,最好能用钥匙从外面开启,因为洗浴时有可能出现晕倒、昏迷甚至中毒等意外,如果不能从外面打开,不利于救护。
另外,浴室锁还应有防水、防锈功能。
(4)通道锁:安在厨房、客厅、餐厅、过厅及儿童房间的门上,只起拉手和撞珠的作用,用来开门关门,没有保险功能。需要提醒的是,儿童房间最好用通道锁,以便于儿童出现意外时,开门救护方便。

2.从外观形状上分,门锁又可分为球形锁、执手锁和呆锁三种。

球形锁和执手锁,把锁、拉手和碰珠三种功能合而为一。
呆锁只有锁和碰珠两种功能,主要安在入户门上,没有把手,开关时不方便,需另外安把手。

以上,仅是一个玩笑。。


二、锁相关概念

什么是可重入锁 :可重入锁的概念是自己可以再次获取自己的内部锁

举个例子,比如一条线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁的时候还是可以获取的(如果不可重入的锁的话,此刻会造成死锁)。说的更高深一点可重入锁是一种递归无阻塞的同步机制。

什么叫读写锁 :读写锁拆成读锁和写锁来理解。读锁可以共享,多个线程可以同时拥有读锁,但是写锁却只能只有一个线程拥有,而且获取写锁的时候其他线程都已经释放了读锁,而且该线程获取写锁之后,其他线程不能再获取读锁。

简单的说就是写锁是排他锁,读锁是共享锁。

获取锁涉及到的两个概念即 公平和非公平 :公平表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO顺序。而非公平就是一种获取锁的抢占机制,和公平相对就是先来不一定先得,这个方式可能造成某些线程饥饿(一直拿不到锁)。

三、锁的类型

按实现分为:

  1. 自旋锁(Spinlock)

    如果锁被占用,尝试获取锁的线程进入busy-wait状态,即CPU不停的循环检查锁是否可用。自旋锁适合占用锁非常短的场合,避免等待锁的线程sleep而带来的CPU两个context switch的开销。

    Spinlock是一把互斥锁,同一时间,只能有一个线程持有Spinlock锁,而所有其他的线程,处于等待Spinlock锁。当持有Spinlock的线程放锁之后,所有等待获取Spinlock的线程一起争抢,一个Lucky的线程,抢到这把锁,大部分Unlucky的线程,只能继续等待下一次抢锁的机会。

    Spinlock,只有带有了Acquire和Release语义,才算是一个真正完整可用的锁——Acquire与Release语义间,构成了一个临界区。获取spinlock后的线程,可以大胆的运行全局变量的读写,而不必担心其他并发线程对于此变量的并发访问。

  2. Semaphores信号量

    如果锁被占用,尝试获取锁的线程进入sleep状态,CPU切换到别的线程。当锁释放之后,系统会自动唤醒sleep的线程。信号量适合对锁占用较长时间的场合。

  3. Adaptive locks自适应锁

    顾名思义,自适应锁就是上面两种的结合。当线程尝试申请锁,会自动根据拥有锁的线程繁忙或sleep来选择是busy wait还是sleep。这种锁只有Solaris内核提供,Linux上未见有相关描述。


按功能分为: (读写锁(Read-Write-Lock))。

1.排它锁(X锁)

排它锁又称为”写锁”,如果事务T对数据对象R加上X锁,则只允许T读取和修改R,其他的任何事务都不能再对R加任何类型的锁,直到T释放R上的X锁。这就保证了在T释放对R的封锁之前,其他事务都不能再读取和修改R。

使用X锁,可以避免”丢失更新”。在一个并发的联机系统中,如果事务T1在修改R前对R加X锁,则事务T2想要更新R的数据必须等待,直到T1完成更新后释放X锁,T2才能对R加X锁。这时T2读到的R是被T1更新后的值,避免了丢失更新。

使用X锁,还可以避免读”脏”数据。如前例,如果事务T1在更新R的记录前对该表加X锁,那么另一个事务T2查询R表的记录也将一直处于等待状态,直到事务T1结束或者撤销,释放X锁,T2才能够检索R表的记里,避免了读”脏”数据。

2.共享锁(S锁)

共享锁又称为”读锁”,如果事务T对数据对象R加S锁,则其他事务也可以对R加S锁,但不能对R加X锁,直到R上的所有S锁释放为止。即共享锁能够阻止对已加锁的数据的更新操作。

对事务中操作的数据对象加X锁可以避免数据一致性被破坏,但是却降低了并发性。使用共享锁,主要防止在读操作期间对数据的修改,因此允许其他事务对数据对象加S锁,完成对同一数据对象的并行读取操作。

如果事务T1在检索R表之前对该表加共享锁,那么在T1结束前,T2不能够获得R表的排它锁,即不能插入新的记录。在T1完成本次操作中对R表的检索后,事务T1结束,这时T2 事务才能够修改R表。