java中的每个对象都可以作为锁,(不要用String,Integer,Long),当synchrozied 在不同位置,锁的对象不一样:
- 普通同步方法,锁是当前实例对象
- 静态同步方法,锁是当前类的class对象
- 同步代码块,锁是括号中的对象
在hospot中synchronized是看对象头的前2位来判断是否有锁。
- synchronized 是可重入锁。
程序在执行过程中,如果出现异常,默认情况锁会被释放
- 所以,在并发处理的过程中,有异常要多加小心,不然可能会发生不一致的情况。
- 比如,在一个web app处理过程中,多个servlet线程共同访问同一个资源,这时如果异常处理不合适,在第一个线程中抛出异常,其他线程就会进入同步代码区,有可能会访问到异常产生时的数据。 因此要非常小心的处理同步业务逻辑中的异常
synchronized的底层实现
JDK早期的synchronized是 重量级的 - OS系统锁
后来改进:
sync (Object)的时候,
-
一开始 markword 记录这个线程ID (偏向锁),如果下次还是当前线程来访问,就可以直接进入了,不用加锁,提高效率。
-
如果出现线程争用:再升级为 自旋锁,这个过程是占用cpu的,在用户态
-
自旋10次以后,升级为重量级锁 - OS系统锁, 内核态,进入等待队列,就不占用cpu了
- 执行时间短(加锁代码),线程数少,用自旋
- 执行时间长,线程数多,用系统锁
这个锁只能升级,不能降级。
网友评论