• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

synchronized(锁)

开发技术 开发技术 1周前 (05-04) 16次浏览

synchronized:互斥锁,本质是通过锁定共享资源,达到线程安全的手段

根据使用方式,分为类锁和对象锁

修饰在静态方法,或者参数为class类的时候,都是以当前类作为共享资源进行锁定,为类锁,粒度最大。

修饰在实例方法,或者参数为指定对象实例的时候,已指定实例为共享资源进行锁定,为对象锁

 

锁的存储:对象头(MarkWord),一个对象作为锁对象,对象头会记录当前的锁状态等一些信息。

偏向锁–>轻量级锁(自旋)–>重量级锁:锁资源的抢占是阻塞的,没有获取到锁资源需要进入阻塞队列内等待唤起,但是一个锁对象并非一定是一直被占有的,所以为了提升性能,存在了锁升级

 

无锁状态–>请求线程直接获取到当前锁对象,此时对象头内记录了当前线程id,因为多数情况下,并不存在锁竞争,大概率还是当前线程来抢占锁资源的可能性最大,所以当线程再次请求,发现锁对象头内就是自身的线程id,不需要再次的加锁和释放锁,可以直接获得,不需再进入阻塞队列等待唤起。这里性能好,降低了竞争的开销

 

锁对象为偏向锁–>新的线程进行请求,发现锁对象存在非本身的线程id,为偏向锁,则通过cas对锁对象的偏向锁进行撤销,如果撤销成功,则获得锁,如果撤销失败,则将当前锁对象升级为轻量级锁,可见偏向锁只有在存在竞争的时候才会释放锁。一般撤销成功的时候,都是持有线程处在安全点的情况下,撤销锁,并不会出现线程安全问题

 

锁对象为轻量锁–>线程在执行同步块之前,JVM会先在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头的MarkWord复制到锁记录中。然后线程会尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁。如果失败,表示其他线程在竞争锁,当前线程使用自旋来获取锁。当自旋次数达到一定次数时,锁就会升级为重量级锁。

轻量级锁解锁时,会使用CAS操作将Displaced Mark Word替换回到对象头,如果成功,表示没有竞争发生。如果失败,表示当前锁存在竞争,锁已经被升级为重量级锁,则会释放锁并唤醒等待的线程。

 

重量级锁–>多个线程争抢同一个锁资源,会将抢夺失败的线程放入阻塞队列内,等待唤起,开销大,性能低

 

线程的通信(wait/notify)

就是线程的阻塞和唤起,在相同的锁对象情况下,通过线程通信切换线程状态。

盗图:

synchronized(锁)

 

 

 

 

死锁:

互斥,共享资源X和Y只能被一个线程占用;

占有且等待,线程T1已经取得共享资源X,在等待共享资源Y的时候,不释放共享资源X;

不可抢占,其他线程不能强行抢占线程T1占有的资源;

循环等待,线程T1等待线程T2占有的资源,线程T2等待线程T1占有的资源,就是循环等待。

 

公平锁非公平锁:非公平锁就是可以插队,公平锁FIFI无法插队

 


程序员灯塔
转载请注明原文链接:synchronized(锁)
喜欢 (0)