对象锁概念
Java的所有对象都含有1个互斥锁,这个锁由JVM主动获取和开释。线程进入synchronized办法的时候获取该对象的锁,当然如果曾经有线程获取了这个对象的锁,那么以后线程会期待,synchronized办法失常返回或者抛异样而终止,JVM会主动开释对象锁。这里也体现了用synchronized来加锁的一个益处,办法抛异样的时候,锁依然能够由JVM来主动开释。
// 对象锁:模式1(办法锁) public synchronized void Method1() { System.out.println("我是对象锁也是办法锁"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } // 对象锁:模式2(代码块模式) public void Method2() { synchronized (this) { System.out.println("我是对象锁"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }
类锁的概念
因为一个class不管被实例化多少次,其中的静态方法和动态变量在内存中都只有一份。所以,一旦一个动态的办法被申明为synchronized。此类所有的实例化对象在调用此办法,共用同一把锁,咱们称之为类锁。
public synchronized static void Method3() { System.out.println("我是类锁"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }}
代码演示类锁和对象锁
上面这段代码是两个类锁和一个对象锁,拿到锁后,睡1秒钟。
// 类锁A public synchronized static void classLockA() { System.out.println("name = " + Thread.currentThread().getName() + ", begain"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("name = " + Thread.currentThread().getName() + ", end"); } // 类锁B public synchronized static void classLockB() { System.out.println("name = " + Thread.currentThread().getName() + ", begain"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("name = " + Thread.currentThread().getName() + ", end"); } // 对象锁 public synchronized void objectLock() { System.out.println("name = " + Thread.currentThread().getName() + ", begain"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("name = " + Thread.currentThread().getName() + ", end"); }
创立三个线程类:别离调用一个资源中的三个办法
class ThreadA extends Thread { private Test02 test02; public ThreadA(Test02 tk) { test02 = tk; } // 调用类锁 public void run() { test02.classLockA(); }}class ThreadB extends Thread { private Test02 test02; public ThreadB(Test02 tk) { test02 = tk; } // 调用类锁 public void run() { test02.classLockB(); }}class ThreadC extends Thread { private Test02 test02; public ThreadC(Test02 tk) { test02 = tk; } // 调用对象锁 public void run() { test02.objectLock(); }}
main办法:起了三个线程,独特拜访一个Test02对象
public static void main(String[] args){ Test02 test02 = new Test02(); ThreadA ta = new ThreadA(test02); ThreadB tb = new ThreadB(test02); ThreadC tc = new ThreadC(test02); ta.setName("A"); tb.setName("B"); tc.setName("C"); ta.start(); tb.start(); tc.start();}
执行的后果:
name = A, begainname = C, begainname = A, endname = B, begainname = C, endname = B, end
能够看出因为 classLockA和classLockB都是类锁,即同一个锁,所以 A和B是按程序执行,即同步的。而C是对象锁,和A/B不是同一种锁,所以C和A、B是 异步执行的。
剖析:
对象锁要想放弃同步执行,那么锁住的必须是同一个对象,举个例子:
Test02类不变,重起两个线程类:均对对象锁进行了调用
class ThreadA extends Thread { private Test02 test02; public ThreadA(Test02 tk) { test02 = tk; } // 调用类锁 public void run() { test02.objectLock(); }}class ThreadB extends Thread { private Test02 test02; public ThreadB(Test02 tk) { test02 = tk; } // 调用类锁 public void run() { test02.objectLock(); }}
main办法:创立两个不同的资源对象,启动两个线程,别离对加锁的办法进行调用
public static void main(String[] args){ Test02 test02 = new Test02(); Test02 test03 = new Test02(); ThreadA ta = new ThreadA(test02); ThreadB tb = new ThreadB(test03); ta.setName("A"); tb.setName("B"); ta.start(); tb.start(); }
后果可见,是异步执行的,没有达到同步的作用。
name = A, begainname = B, begainname = A, endname = B, end
改良:只需对类锁进行调用,代码如下:
class ThreadA extends Thread { private Test02 test02; public ThreadA(Test02 tk) { test02 = tk; } // 调用类锁 public void run() { test02.classLockA(); }}class ThreadB extends Thread { private Test02 test02; public ThreadB(Test02 tk) { test02 = tk; } // 调用类锁 public void run() { test02.classLockA(); }}
main办法:同样是创立了多个对象
public static void main(String[] args){ Test02 test02 = new Test02(); Test02 test03 = new Test02(); ThreadA ta = new ThreadA(test02); ThreadB tb = new ThreadB(test03); ta.setName("A"); tb.setName("B"); ta.start(); tb.start(); }
后果达到了同步的成果!
name = A, begainname = A, endname = B, begainname = B, end
总结:
- 如果多线程同时拜访同一类的 类锁(synchronized 润饰的静态方法)以及对象锁(synchronized 润饰的非静态方法)这两个办法执行是异步的,起因:类锁和对象锁是2中不同的锁。
- 类锁对该类的所有对象都能起作用,而对象锁不能。
- synchronized锁的是对象。