类有一个特性叫封装,若是一个类,全部的field都是private的,并且没有任何的method,那么这个类就像是四面围墙+天罗地网,没有门。看起来就是一个封闭的箱子,外面的进不来,里面的出不去,通常来讲,这样的类是没用的。多线程
synchronized(obj){ // some code... }
这个用法就是使用了obj的锁,来锁定一个代码块。并发
1 publicsynchronizedvoid aMethod(){ 2 // some code... 3 }
这个时候它使用的是当前实例this的锁,至关于下面的模式:性能
publicvoid aMethod(){ synchronized(this){ // some code... } }
1 class SyncData { 2 public void do1() { 3 synchronized(this) { 4 for (int i=0; i < 4; i++) { 5 System.out.println(Thread.currentThread().getName() + "-do1-" + i); 6 try{ 7 Thread.sleep(1000); 8 }catch(InterruptedException e) { 9 e.printStackTrace(); 10 } 11 } 12 } 13 14 } 15 16 public void do2() { 17 synchronized(this) { 18 for (int i=0; i < 4; i++) { 19 System.out.println(Thread.currentThread().getName() + "-do2-" + i); 20 try{ 21 Thread.sleep(1000); 22 }catch(InterruptedException e) { 23 e.printStackTrace(); 24 } 25 } 26 } 27 } 28 }
建立1个SyncData的实例,开启2个线程,一个线程调用实例的do1方法,另外一个线程调用实例的do2方法,你会看到他们之间是互斥的——即便2个线程访问的是实例的不一样的方法,依然不能同时访问。由于决定是否能够同时访问的再也不是门,而是锁。只要使用的是相同的对象锁,就会互斥访问。this
1 class SyncData { 2 private Object lock = new byte[0]; 3 4 public void do1() { 5 synchronized(lock) { 6 for (int i=0; i < 4; i++) { 7 System.out.println(Thread.currentThread().getName() + "-do1-" + i); 8 try{ 9 Thread.sleep(1000); 10 }catch(InterruptedException e) { 11 e.printStackTrace(); 12 } 13 } 14 } 15 } 16 }
思考下面的代码是否能起到互斥访问的做用:spa
1 class SyncData { 2 public void do1() { 3 Object lock = new byte[0]; 4 synchronized(lock) { 5 for (int i=0; i < 4; i++) { 6 System.out.println(Thread.currentThread().getName() + "-do1-" + i); 7 try{ 8 Thread.sleep(1000); 9 }catch(InterruptedException e) { 10 e.printStackTrace(); 11 } 12 } 13 } 14 } 15 }
这个是不能起到互斥做用的,由于每一次调用,局部变量lock都是不一样的实例。也就是说,synchronized使用的锁老是变化的。因此咱们再补充一点:只有使用相同的对象锁,才能互斥访问。因此识别所使用的锁,是很重要的。.net
1 class SyncData { 2 public void do1() { 3 synchronized(this) { 4 for (int i=0; i < 4; i++) { 5 System.out.println(Thread.currentThread().getName() + "-do1-" + i); 6 try{ 7 Thread.sleep(1000); 8 }catch(InterruptedException e) { 9 e.printStackTrace(); 10 } 11 } 12 } 13 14 } 15 }
建立2个实例,分别交给2个线程中的1个去访问,能互斥吗?线程
class SyncData { public void do1() { synchronized(this.getClass()) { for (int i=0; i < 4; i++) { System.out.println(Thread.currentThread().getName() + "-do1-" + i); try{ Thread.sleep(1000); }catch(InterruptedException e) { e.printStackTrace(); } } } } }
能够互斥,无论一个类有多少个实例,它们调用getClass()返回的结果都是同一个实例。设计