一、公平锁与非公平锁

线程所谓的公平,就是指的是线程是否按照锁的申请顺序来获取锁,如果是遵守顺序来获取,这就是个公平锁,反之为非公平锁。

  非公平锁的优点在于吞吐量大,但是由于其不是遵循申请锁的顺序来获取锁,就会出现最开始申请的锁一直没有获取到,导致出现饥饿现象。

  java中的使用:

  synchronized:非公平锁

  ReentrantLock:按照其构造方法来指定该锁是否是公平锁,默认是非公平锁

二、共享锁与排他锁

排他锁:该锁只能被一个线程使用;

  共享锁:该锁可被多个线程所使用;

  java中的使用:

  synchronized:排他锁(这是必然的)

  ReentrantLock:排他锁 

  ReadWriteLock:ReadWriteLock中分为读写两个锁,其中读锁是共享锁,写锁是排他锁,这样的好处就是使得这个锁资源利用率高,因为只是读的话不会改变内容。

三、偏向锁、轻量级锁、重量级锁

 这三种只的是锁的状态,并且这三个锁只针对于synchronized

  偏向锁:当其他线程竞争时,才会释放的锁。这个锁的存在是因为获取锁和释放锁是非常浪费资源的,如果只有一个线程,偏向锁是非常好的一个选择。

  轻量级锁:当多线程任务是原子性操作时,可以同时让多个线程进入同步代码块。这锁是由偏向锁中从单线程变成多线程时演变的。

  重量级锁:当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。

  在JDK5之前,synchronized一直都是重量级锁。

四、锁重入

锁重入是指在多线程环境中,如果有两个线程A、B,且A、B两个线程都获取了同一把锁,如果此时只有A线程调用了B线程,A会自动获取B中的锁。锁重入的好处是能够避免死锁。

  synchronized与ReentrantLock都是锁重入。

五、自旋锁

在Java中,自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。

六、死锁、活锁、饥饿

这三个是线程的状态:

  死锁:当一个线程获取了锁,其他线程也来获取就会发生死锁

  活锁:当两个线程同时获取同一个资源,如果都发现了对方在获取这个资源,那么双方会停止访问又去同时访问另一相同资源,如此反复就产生了活锁。

  饥饿:优先级较低的线程无法执行

七、乐观锁与悲观锁

悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。

  乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。

  java中的使用:

  悲观锁:synchronized

  乐观锁:JDK的原子性操作类java.util.concurrent.atomic