Java中的锁

为什么会有这些锁呢?

因为一种类型的锁很难应对线程操作同步资源的情况。

  1. 乐观锁和悲观锁

  2. 自旋锁和适应性自旋锁

  3. 无锁、偏向锁、轻量级锁和重量级锁

  4. 公平锁和非公平锁

  5. 可重入锁和非可重入锁

乐观锁和悲观锁

悲观锁认为当它操作数据的时候,必然用一个线程和它争抢。因此它每一次操作时都会给数据加锁。

乐观锁认为自己在操作数据时,不会有其他线程来操作,所以不加锁,只是在更新的时候判断之前有没有别的线程更新了这个数据。没有更新则写入,更新了则不写入。

自旋锁和适应性自旋锁

自旋锁就是在获取一个资源的时候,判断当前的锁是不是自旋锁,如果是自旋锁,则不放弃cpu时间片,不断地获取资源,直到拿到资源。如果在自旋完成之前,线程释放了资源,当前线程就可以不必阻塞而是直接获取同步资源,从而避免切换线程的开销。这就是自旋锁。

适应性锁说的就是让自旋等待的时间不再固定。当一个线程自旋过后能获取到锁,那么JVM就认为自旋获取锁的概率比较大,会自动增加等待时长。反正,自旋等待很少获取到锁,那么以后要获取这个锁可能省略掉自旋过程,避免资源浪费。

无锁、偏向锁、轻量级锁和重量级锁

偏向锁通过比较Mark Word解决加锁问题,避免执行CAS操作,而轻量级锁通过CAS操作和自旋来解决加锁问题,避免线程阻塞和唤醒而影响性能。重量级锁是将除了拥有锁的线程以外的线程都阻塞。

因为阻塞是非常消耗资源的,所以加入了这三种锁机制。最坏的情况是重量级锁。

公平锁和非公平锁

公平锁说的就是按线程请求锁的顺序来获取锁。线程是直接进入队列中排队。

非公平锁说的是多个线程加锁时,会直接尝试获取锁,如果获取不到在进入等待队列的队尾等待。锁如果刚好可用,那么这个线程无需阻塞直接获取锁。

可重入锁和非可重入锁

可重入锁是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。

独享锁和共享锁

独享锁也叫排他锁,是指该锁一次只能被一个线程所持有。如果线程T对数据A加上排它锁后,则其他线程不能再对A加任何类型的锁。获得排它锁的线程即能读数据又能修改数据。JDK中的synchronized和JUC中Lock的实现类就是互斥锁。

共享锁是指该锁可被多个线程所持有。如果线程T对数据A加上共享锁后,则其他线程只能对A再加共享锁,不能加排它锁。获得共享锁的线程只能读数据,不能修改数据。

你可能感兴趣的:(jvm,java,开发语言)