Java之偏向锁、轻量级锁、互斥锁

自旋锁

一般都是采用一个循环来占用某个资源,可想而知,它不适合对某个资源长期占用,采用循环会严重损耗CPU性能。

CAS

CAS即Compare and Set,即比较和设置的意思,它的核心思想是通过比较预期值和原值是否一样,如果不一样,则进行修改成预期,如果一样就返回false。Java里AtomicInteger.compareAndSet(int,int);就是典型的CAS操作。
细心的读者会发现,如果一个值原来是A,变成了B,然后又变成了A,这时候另外的线程访问的时候,发现值没有变化,但实际上已经发生了变化,从而导致更新这个值。
解决的常用办法是:设置一个版本号version,每次读取的时候,顺便将version也读取出来,写回的时候,若当前读出的version+1比记录中的version大,则写入,这个比较大小与写入操作必选是原子的。
试想一种应用场景,两个线程都读取到某一资源,都读取到了version字段信息,其中一个线程率先写回,在写回的时候,发现读到的version+1>记录中的version,则将记录中的version设置程version+1,另一个线程写回的时候,发现version+1==记录中的version了,这时候,它就自旋,重新读取version,然后再重复上面的操作。

偏向锁

在对象头和帧栈中记录偏向线程的ID,下次再访问该资源的时候,无需争抢,可直接获取到该资源,这就好像你去借书,借书之前需要争抢,借到该书之后,该书就暂时属于你一样。
由于多个线程并发同一资源的时候,发现总是由同一线程获取到锁,这时候,偏向锁是你要的,当多个线程并发的时候,偏向的线程无需争抢锁,发现有自身的ID,则可直接拿到资源。

轻量级锁

一般是由CAS加自旋判断来实现,应用在追求相应时间,但是这种锁相对互斥锁而言,更加消耗CPU性能,因为自旋会产生较大开销。

重量级锁(互斥锁)

synchronized就是一种重量级锁,当轻量级锁的自旋时间太长,那么就会蜕化成互斥锁。

猜你喜欢

转载自blog.csdn.net/qq_25956141/article/details/81806968