对象锁和类锁的区别
无论是对象锁还是类锁,我们分析的标准就是我们要获取的资源是否与创建新的对象有关。比如类信息、静态变量的数据无论创建多少个对象都只存在一份,而成员变量这种随着新对象的创建而创建。
类锁就是用在整个类上的锁,对象锁是用在实例上的锁。
对象锁还要分为对谁上锁:
- 对非静态变量上锁:只在当前线程或者当前对象上会发生阻塞,也就是不同的实例就不会阻塞,因为这些变量不是对类的,而是实例所有的。
- 对非静态方法上锁:只在当前线程或者当前对象上会发生阻塞
- 对this本身的实例上锁:只在当前线程或者当前对象上会发生阻塞
- 对static相关的上锁:他是共享的一个锁,所以不同的对象在不同线程进行获得锁,会因为没有获得到锁产生阻塞。
凡是在堆和方法区的变量做锁获取的资源,都会涉及到这些问题。
类锁:
是放在加载类上,类信息在方法区,整个JVM只有一份,所以他无论在什么时候都是阻塞的。实现方式
- 在static的方法上加synchronized
- 在static变量上加synchronized
- synchronized获取Class对象
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| class ObjectLock{ private Object object = new Object(); private static Object staticObject = new Object(); private static volatile ObjectLock singleton; public void nonStaticVariable() throws InterruptedException { synchronized(object) { System.out.println(this); System.out.println("ObjectLock"); Thread.sleep(1000); } } public synchronized void nonStaticMethod() throws InterruptedException { System.out.println("ObjectLock Method"); Thread.sleep(1000); } public void nonStaticThis() throws InterruptedException { synchronized(this) { System.out.println(this); System.out.println("ObjectLock This"); Thread.sleep(1000); } } public static ObjectLock getSingleton() throws InterruptedException { if (singleton == null) { synchronized (ObjectLock.class) { if (singleton == null) { singleton = new ObjectLock(); } } } return singleton; } public void staticVariable() throws InterruptedException { synchronized(staticObject) { System.out.println(this); System.out.println("ObjectLock Static Variable"); Thread.sleep(1000); } } public synchronized static void staticMethod() throws InterruptedException { System.out.println("ObjectLock Static Method"); Thread.sleep(1000); }
public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { ObjectLock objectLock = null; try { objectLock = ObjectLock.getSingleton(); } catch (InterruptedException e) { e.printStackTrace(); } try { objectLock.staticVariable(); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { ObjectLock objectLock = null; try { objectLock = ObjectLock.getSingleton(); } catch (InterruptedException e) { e.printStackTrace(); } try { objectLock.staticVariable(); } catch (InterruptedException e) { e.printStackTrace(); } } });
t1.start(); t2.start(); } }
|