同步锁:当多个线程使用同一个资源共享时,会出现资源抢夺,对于每个进程而言,他们去抢占同一个资源,所得到的结果是不确定的。同步锁就解决了这个问题。在给定的代码块加上Synchronized(this){代码块}。当线程进入到锁时,其它线程就算抢到cpu的执行权也只有在锁外面,无法进入。
死锁:多线程情况下,假设存在锁A和锁B,线程A进入抢夺到A,还没有释放锁,在代码块中又遇到了锁B,因为一个线程不能同时抢夺到不同的两个锁,所以该线程就会形成阻塞状态,无法释放锁,其它线程也无法拿到锁,一直处于阻塞状态。
乐观锁:指的是在操作数据的时候非常乐观,乐观地认为别人不会同时修改数据,因此乐观锁默认是不会上锁的,只有在执行更新的时候才会去判断在此期间别人是否修改了数据,如果别人修改了数据则放弃操作,否则执行操作。
悲观锁:指的是在操作数据的时候比较悲观,悲观地认为别人一定会同时修改数据,因此悲观锁在操作数据时是直接把数据上锁,直到操作完成之后才会释放锁,在上锁期间其他人不能操作数据。
乐观锁的实现:简单理解(操作数据的过程中会存在一个version值,在线程操作数据后会判断该version值是否改变,如果改变了,则该线程的这次操作作废)
注意:乐观锁不是锁,而是底层又记录数据是否改变的值
悲观锁:对要执行的资源加上Synchronized同步锁,不管是否会冲突都加上。保证了线程安全。
缺点:因为要加锁,形成阻塞,导致效率低。
锁升级过程
先是无锁状态,线程在请求锁的时候,先是无锁状态的,当进入到jvm请求锁的时候,会请求到偏向锁,偏向锁会通过cas将自己线程的id记录到对象头mark-word里面,多线程情况下,线程来访问的时候,会先判断对象头mark-word里面记录的线程id是否是自己线程的id,如果一致,就进入锁开始执行,如果不一致则无法进入,因为
多线程下,偏向锁没有自旋的机制,所以其它线程会一直处于阻塞状态,此时,锁升级为轻量级锁,轻量级锁提供了自旋的功能,允许没有执行权的线程自旋,如果出现大量线程来访问锁,就会造成大量线程自旋,非常消耗资源,所以锁会升级为重量级锁,线程进入重量级锁,重量级锁是系统分配的,非常底层,会涉及用户态和内核态之间的转换,但是重量级锁存在一个机制,就是线程自旋一段时间,便会到EntryList等待,不会消耗大量资源。
可重入锁:
连续进入到相同的两把锁。
公平锁,不公平锁:
公平锁:多个线程来抢锁,先进入到队列中等待,等抢到cpu的线程执行完毕,再唤醒先进入队列中的线程来执行。
不公平锁:多个线程来抢锁,后来的线程直接到cas判断锁的状态,如果没有线程在执行,就直接抢得锁对象,如果没有强到,然后再进入队列中等待。