乐观锁与悲观锁
- 悲观锁比较悲观,当多个线程对同一行数据实现写的操作的时候,最终只会有一个线程才能写成功,只要谁能获取到行锁则其他线程时不能对该行数据做任何修写操作,且是阻塞状态。
- 乐观锁比较乐观,通过预值或者版本号比较,如果不一致性的情况则通过循环控制修改,当前线程不会被阻塞,是乐观的。
偏向锁与重入锁
- 重入锁的话比如当使用lock锁的时候调用第一次的时候进行cas操作成功只会存放当前线程exclusiveOwnerThread,当第二次调用lock()的时候只会让state+1。在调用unlock()方法的时候如果state不为0就不会释放锁。只会修改state状态。
- synchronized和Lock具有可重入性是可重入锁,如果锁不具有可重入性,当前线程递归调用方法中有可能会发生死锁问题。
- 偏向锁如果当前只有一个线程的情况下,锁会被线程一直持有。只有在有其它线程竞争锁时才会撤销偏向锁。
- 重入锁会判断重入的次数,如果为0则会释放锁
公平锁与非公平锁
在ReentrantLock的构造方法中可以设置是否为公平锁
- 公平锁:每次获取锁会根据请求的顺序进行执行,类似队列
- 非公平锁:每次获取锁会进行竞争
轻量级锁与重量级锁
- 轻量级都是在用户态[运行用户程序(用户空间)]完成;
- 重量级需要用户态与内核态[运行操作系统程序,操作硬件 (内核空间)]切换;
重量级锁需要通过 操作系统自身的互斥量(mutex lock,也称为互斥锁)来实现 / 使用C++的monitor对象实现的。
然而这种实现方式需要通过用户态和内核态的切换来实现,但这个切换的过程会带来很大的性能开销。
死锁
两个(或以上)线程互相获取对方已经拥有的资源而形成的对峙局面,成为死锁。在没有外部条件的干涉下,程序无法向下执行,一直阻塞。
产生死锁的四个必要条件如下:
- 互斥条件:每个资源只能同时被一个线程占用。如果一个线程占用了某个资源,其他线程就无法同时占用它。
- 请求与保持条件:一个进程至少持有一个资源时,同时正在等待获取其他进程持有的资源。
- 不可剥夺条件:资源不能被强制从占有的进程中夺走,进程必须使用完毕后才能释放资源。
- 循环等待条件:存在一种等待关系,即进程等待链中的下一个进程所持有的资源,形成了一个循环圈。