方法锁和对象锁效果相同,同一对象的引用阻塞,不同对象引用不阻塞
类锁 :静态的方法和变量,即使类实例化多次,也只存在一份,同一对象的引用阻塞,不同对象引用也会阻塞;
类可以实例化多个对象,但只有一个class , 锁住class; 同一对象的引用阻塞,不同对象引用也会阻塞
每个对象都有一把锁,由jvm进行获取锁和释放锁。
static int s=0;
int i=0;
public void getI(){
//对象锁 ,同一对象的引用阻塞,不同对象引用不阻塞
synchronized (this){
int j=0;
while (j++<5){
i++;
System.out.println(Thread.currentThread().getName()+"==="+i);
}
}
}
public synchronized void getI2(){
//方法锁 ,同一对象的引用阻塞,不同对象引用不阻塞
int j=0;
while (j++<5){
i++;
System.out.println(Thread.currentThread().getName()+"==="+i);
}
}
public synchronized static void getI3(){
//静态的方法和变量,即使类实例化多次,也只存在一份,同一对象的引用阻塞,不同对象引用也会阻塞
int j=0;
while (j++<5){
s++;
System.out.println(Thread.currentThread().getName()+"==="+s);
}
}
public void getI4(){
//类锁,类可以实例化多个对象,但只有一个class , 同一对象的引用阻塞,不同对象引用也会阻塞
//获取class 的三种方式
//1.Dog dog = new Dog() dog.getclass
//2.Dog.class
//3.Class class = class.forname("com.xxx.Dog");
synchronized (SynTest.class){
int j=0;
while (j++<5){
s++;
System.out.println(Thread.currentThread().getName()+"==="+s);
}
}
}
synchronized 的锁是基于JVM的获取和释放,有一个monitor对象,获取锁和释放锁的过程就是进入monitor 和退出 monitor的过程。synchronized (this) 通过 monitorenter 和monitorexit 指令执行
synchronized void method() 时 常量池中会有ACC_SYNCHRONIZED , 方法调用时先判断ACC_SYNCHRONIZED 标记位,如果设置了,就获取monitor对象,执行完后再释放monitor。
对象在jvm中的存储布局: 对象头,实例数据,和对齐填充
对象头包括存储对象自身的运行时数据,类型指针,若为对象数组,还应有记录数组长度的数据。
运行时数据包括 哈希码,GC分代年龄,锁状态标识,线程持有的锁,偏向线程ID,偏向时间戳。
网友评论