java类锁与对象锁

1、我们先了解下java几个内存区特性更有助于我们理解对象锁和类锁,JVM内存区粗略可以分为栈区、堆区、方法区、程序计数器;

(1)栈区:主要存储的是局部变量值和对象引用,常量池的引用,每个线程私有;

(2)堆区:主要存储的是对象实例、数组,所有线程共享此区域;

(3)方法区:主要存储静态变量、静态常量、静态方法、类信息,所有线程共享此区域;

(4)程序计数器:当前程序执行指令的地址,每个线程私有;






2、什么是类锁,什么是对象锁他们在并发环境下的问题;


(1)首先我们区分一下类和对象的区别

类(即class):是虚拟机在编译期间产生的,同一个类在一个系统里面只会存在一个,它和静态变量和静态常量都存储在内存的方法区;

对象:是在运行期间产生的,同一个系统可以产生(new)同一个类型的多个对象,它存储在内存的堆区中;


(2)类锁和对象锁

类锁:锁是加持在类上的,用synchronized static 或者synchronized(class)方法使用的锁都是类锁,因为class和静态方法在系统中只会产生一份,所以在单系统环境中使用类锁是线程安全的;


案例:

public class TestLock {

public synchronized static void methodName1() {
System.out.println("类锁方式一");
}

public void methodName2() {
synchronized (TestLock.class) {
System.out.println("类锁方式二");
}
}
}




对象锁:synchronized 修饰非静态的方法和synchronized(this)都是使用的对象锁,一个系统可以有多个对象实例,所以使用对象锁不是线程安全的,除非保证一个系统该类型的对象只会创建一个(通常使用单例模式)才能保证线程安全;


案例:单例模式保证对象锁安全

public class TestLock {

private static TestLock testLock=null;

//私有化构造函数不允许new来产生对象
private TestLock() {
}

//保证一个系统只会创建一个对象实例
public synchronized static TestLock GetInstance() {
if (testLock == null) {
synchronized (TestLock.class) {
if (testLock == null) {
testLock = new TestLock();
}
}
}
return testLock;
}

public synchronized void methodName1() {
System.out.println("对象锁方式一");
}

public void methodName2() {
synchronized (TestLock.this) {
System.out.println("对象锁方式二");
}
}
}

发布于 2017-11-29