- 自旋与阻塞
- 当一个线程拿不到锁的时候,有以下两种基本的等待策略
- 放弃CPU,进入阻塞状态,等待后续被唤醒,再重新被操作系统调度。
- 不放弃CPU,空转,不断重试,也就是所谓的“自旋”。
- 很显然,如果是单核的CPU,只能用策略1。因为如果不放弃CPU,那么其他线程无法运行,也就无
法释放锁。但对于多CPU或者多核,策略2就很有用了,因为没有线程切换的开销。
- synchronized
- 如果获取不到锁,先自旋;如果自旋还拿不到锁,再阻塞
- 当一个线程拿不到锁的时候,有以下两种基本的等待策略
- 行锁和表锁
- 乐观锁(CAS)和悲观锁
- 悲观锁:认为数据发生并发冲突的概率很大,读操作之前就上锁。synchronized关键字,后面
要讲的ReentrantLock都是悲观锁的典型。 - 乐观锁 :认为数据发生并发冲突的概率比较小,读操作之前不上锁。等到写操作的时候,再判
断数据在此期间是否被其他线程修改了。如果被其他线程修改了,就把数据重新读出来,重复该过程;
如果没有被修改,就写回去。判断数据是否被修改,同时写回新值,这两个操作要合成一个原子操作,
也就是CAS ( Compare And Set )。
- 悲观锁:认为数据发生并发冲突的概率很大,读操作之前就上锁。synchronized关键字,后面
- 锁的公平性vs.非公平性
- 一个新的线程来了之后,看到有很多线程在排队,自己排到队伍末尾,这叫公
平;线程来了之后直接去抢锁,这叫作不公平。默认设置的是非公平锁,其实是为了提高效率,减少线
程切换。
- 一个新的线程来了之后,看到有很多线程在排队,自己排到队伍末尾,这叫公
- 读写锁实现原理
