关于锁--起源

最近在设计分布式系统中以及性能优化中都会多多少少用到一些锁,又经常被人问到,闲暇之时总结一下关于锁的一些理解。

锁的出现是因为有并发,当完全串行的时候,你根本不需要考虑某个资源会被多个消费者消费的情况,完全是一种瀑布流模式。但是如果串行的弊端(等待)成为瓶颈的时候,我们会引入并发来优化系统,这样就会导致同一个资源会被多个消费者同时来消费。最简单的例子,执行i++的时候,系统会进行两次操作,第一次将i的值从内存中读入CPU,在CPU中进行加1之后再写回内存中,当有两个线程对同一个变量执行这个操作的时候,两个线程可能会从内存中读取到相同的值,都进行了加1操作,然后又都写回到了内存,这样就会造成错误。在这种情况下,我们就需要一种机制,以保证在执行i++的时候,不会出现多个线程同时执行的情况,这种机制就是锁。这种锁是排他锁,也叫X锁。

但是是不是都需要排他锁呢?性能优化的一个很大的原则是不要让资源处于吃不饱状态。如果在任何时候都加上X锁,那会有什么情况呢?再举个例子,有一个公共字段,有一些线程需要去读这个字段,有一些线程需要去修改这个字段,但是是不是都加X锁合适呢?想一想,如果这些只读的线程,并未对该字段做修改操作,这些线程即使并发读取也没有什么关系,大家都不会修改这个变量值。但是不加锁行不行呢?不加锁的话,一旦一个修改的线程修改了这个变量就会引起来读得线程读取到错误的数据。由此可见,这个地方也需要一把锁,但是这个锁比X锁要低一些,允许同时读,这种锁是共享锁,也叫S锁。

再回到刚才说那个问题,如果多个线程同时读这个变量的时候,这些线程持有S锁,这个时候来个一个写得请求,怎么办?换锁!首先要等这些读的线程执行完读操作,然后写线程对变量加上X锁,加上这个锁之后,再来的读请求就会请求不到锁,就不能读了,等写线程完成写操作后,再将锁释放掉,这个时候读得线程才会获得加锁机会,加上S锁。

下节再说说锁的实现。

猜你喜欢

转载自jianfeihit.iteye.com/blog/2028463
今日推荐