synchronized(锁)
synchronized:互斥锁,本质是通过锁定共享资源,达到线程安全的手段
根据使用方式,分为类锁和对象锁
修饰在静态方法,或者参数为class类的时候,都是以当前类作为共享资源进行锁定,为类锁,粒度最大。
修饰在实例方法,或者参数为指定对象实例的时候,已指定实例为共享资源进行锁定,为对象锁
锁的存储:对象头(MarkWord),一个对象作为锁对象,对象头会记录当前的锁状态等一些信息。
偏向锁-->轻量级锁(自旋)-->重量级锁:锁资源的抢占是阻塞的,没有获取到锁资源需要进入阻塞队列内等待唤起,但是一个锁对象并非一定是一直被占有的,所以为了提升性能,存在了锁升级
无锁状态-->请求线程直接获取到当前锁对象,此时对象头内记录了当前线程id,因为多数情况下,并不存在锁竞争,大概率还是当前线程来抢占锁资源的可能性最大,所以当线程再次请求,发现锁对象头内就是自身的线程id,不需要再次的加锁和释放锁,可以直接获得,不需再进入阻塞队列等待唤起。这里性能好,降低了竞争的开销
锁对象为偏向锁-->新的线程进行请求,发现锁对象存在非本身的线程id,为偏向锁,则通过cas对锁对象的偏向锁进行撤销,如果撤销成功,则获得锁,如果撤销失败,则将当前锁对象升级为轻量级锁,可见偏向锁只有在存在竞争的时候才会释放锁。一般撤销成功的时候,都是持有线程处在安全点的情况下,撤销锁,并不会出现线程安全问题
锁对象为轻量锁-->线程在执行同步块之前,JVM会先在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头的MarkWord复制到锁记录中。然后线程会尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁。如果失败,表示其他线程在竞争锁,当前线程使用自旋来获取锁。当自旋次数达到一定次数时,锁就会升级为重量级锁。
轻量级锁解锁时,会使用CAS操作将Displaced Mark Word替换回到对象头,如果成功,表示没有竞争发生。如果失败,表示当前锁存在竞争,锁已经被升级为重量级锁,则会释放锁并唤醒等待的线程。
重量级锁-->多个线程争抢同一个锁资源,会将抢夺失败的线程放入阻塞队列内,等待唤起,开销大,性能低
线程的通信(wait/notify)
就是线程的阻塞和唤起,在相同的锁对象情况下,通过线程通信切换线程状态。
盗图:

死锁:
互斥,共享资源X和Y只能被一个线程占用;
占有且等待,线程T1已经取得共享资源X,在等待共享资源Y的时候,不释放共享资源X;
不可抢占,其他线程不能强行抢占线程T1占有的资源;
循环等待,线程T1等待线程T2占有的资源,线程T2等待线程T1占有的资源,就是循环等待。
公平锁非公平锁:非公平锁就是可以插队,公平锁FIFI无法插队

浙公网安备 33010602011771号