类锁
类锁 !!!! java类有很多对象 ,但是只有一个class对象 !!!!
所以,类锁,就是针对当前类的Class对象的锁
类锁同一时刻只能被一个对象获取
- synchronized放在static方法上(静态锁)
- synchronized放在class对象上
静态锁
class SyncClassStatic implements Runnable { @Override public void run() { method(); } public static synchronized void method() { System.out.println("我是类锁中静态锁"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"运行结束"); }}result:我是类锁中静态锁Thread-6运行结束我是类锁中静态锁Thread-7运行结束类锁,静态锁运行完毕
class对象锁
class SyncClassObj implements Runnable{ @Override public void run() { method(); } private void method(){ synchronized (SyncClassObj.class) { System.out.println("我是类锁中class对象锁"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"运行结束"); } }}result:我是类锁中class对象锁Thread-8运行结束我是类锁中class对象锁Thread-9运行结束类锁,class对象运行完毕
常见场景和问题
-
两个线程同时访问一个对象的同步方法会怎样?
依次执行(锁住的是同一个对象)
-
两个线程访问的是两个对象的同步方法又会怎样?
随机执行(锁住的是不同的对象)
-
两个线程访问的是synchronized的静态方法会怎样?
依次执行(锁住的是同一个类)
-
同时访问同步方法与非同步方法会怎样?
只锁加了synchronized的方法,其他方法不会收到影响
class SyncObjLock implements Runnable { @Override public void run() { if(Thread.currentThread().getName().equals("Thread-0")) { syncMethod(); }else{ asyncMethod(); } } private synchronized void syncMethod() { System.out.println("我被锁了"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"运行结束"); } private void asyncMethod() { System.out.println("我没被锁"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"运行结束"); }}同时开始,同时结束:我被锁了我没被锁Thread-0运行结束Thread-1运行结束
- 访问同一个对象的不同的普通同步方法会怎样?
class SyncDiff implements Runnable{ @Override public void run() { if(Thread.currentThread().getName().equals("Thread-0")) { syncMethod1(); }else{ syncMethod2(); } } private synchronized void syncMethod1() { System.out.println("我被锁了,我是方法1"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"运行结束"); } private synchronized void syncMethod2() { System.out.println("我被锁了,我是方法2"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"运行结束"); }}同时开始,同时结束:我被锁了我没被锁Thread-0运行结束Thread-1运行结束
- 同时访问静态sync和非静态sync方法
class SyncStaticOrNo implements Runnable { @Override public void run() { if(Thread.currentThread().getName().equals("Thread-0")) { syncMethod1(); }else{ syncMethod2(); } } private synchronized void syncMethod1() { System.out.println("我被对象锁"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"运行结束"); } private static synchronized void syncMethod2() { System.out.println("我是类锁"); try{ Thread.sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"运行结束"); }}同时开始,同时结束:我被锁了我没被锁Thread-0运行结束Thread-1运行结束
- 方法抛出异常后,会释放锁吗?
会,jvm帮我们释放了
class SyncExc implements Runnable{ @Override public void run() { method1(); } private synchronized void method1() { System.out.println(Thread.currentThread().getName()+"开始"); try{ Thread.sleep(3000); }catch (Exception e) { e.printStackTrace(); } throw new RuntimeException("");// System.out.println("运行结束"); }}
Thread-0开始Exception in thread "Thread-0" java.lang.RuntimeException: at Thread.SyncExc.method1(SynchronizedObject.java:187) at Thread.SyncExc.run(SynchronizedObject.java:176) at java.lang.Thread.run(Thread.java:748)Thread-1开始Exception in thread "Thread-1" java.lang.RuntimeException: at Thread.SyncExc.method1(SynchronizedObject.java:187) at Thread.SyncExc.run(SynchronizedObject.java:176) at java.lang.Thread.run(Thread.java:748)
锁的使用场景及分析
整个系统全局同步用类锁,局部锁用对象锁
对比下,就像一样,锁的范围越大,性能自然越低(粒度:类锁>对象锁 性能:类锁<对象锁)