1、悲观锁和乐观锁
悲观锁:当前线程去操作数据的时候,总是认为别的线程会去修改数据,所以每次操作数据的时候都会上锁,别的线程去操作数据的时候就会阻塞,比如synchronized;
乐观锁:当前线程每次去操作数据的时候都认为别人不会修改,更新的时候会判断别人是否会去更新数据,通过版本来判断,如果数据被修改了就拒绝更新,例如cas是乐观锁,但是严格来说并不是锁,通过原子性来保证数据的同步,例如数据库的乐观锁,通过版本控制来实现,cas不会保证线程同步,乐观的认为在数据更新期间没有其他线程影响
总结:悲观锁适合写操作多的场景,乐观锁适合读操作多的场景,乐观锁的吞吐量会比悲观锁高
2、公平锁和非公平锁
公平锁:有多个线程按照申请锁的顺序来获取锁,就是说,如果一个线程组里面,能够保证每个线程都能拿到锁,例如:ReentrantLock(使用的同步队列FIFO)
非公平锁:获取锁的方式是随机的,保证不了每个线程都能拿到锁,会存在有的线程饿死,一直拿不到锁,例如:synchronized,ReentrantLock
总结:非公平锁性能高于公平锁,更能重复利用CPU的时间
3、可重入锁和不可重入锁
可重入锁:也叫递归锁,在外层使用锁之后,在内层仍然可以使用,并且不会产生死锁
不可重入锁:在当前线程执行某个方法已经获取了该锁,那么在方法中尝试再次获取锁时,就会获取不到被阻塞
总结:可重入锁能一定程度的避免死锁,例如:synchronized,ReentrantLock
4、自旋锁
自旋锁:一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环,任何时刻最多只能有一个执行单元获得锁
总结:不会发生线程状态的切换,一直处于用户态,减少了线程上下文切换的消耗,缺点是循环会消耗CPU
5、共享锁和独享锁
共享锁:也叫读锁,可以查看数据,但是不能修改和删除的一种数据锁,加锁后其他的用户可以并发读取,但不能修改、增加、删除数据,该锁可被多个线程持有,用于资源数据共享
独享锁:也叫排它锁、写锁、独占锁、独享锁,该锁每一次只能被一个线程所持有,加锁后任何线程试图再次加锁都会被阻塞,直到当前线程解锁。例如:线程A对data加上排它锁后,则其他线程不能再对data加任何类型的锁,获得互斥锁的线程既能读数据又能修改数据