上面的代码,同一时刻只能有一个线程能够获得testLock对象的锁。其他对象想要获得这个对象的锁的时候必须要等待上一个线程释放了这个锁后才能先获得这个对象的锁再执行。锁一个对象有一个好处就是,在锁这个对象的同时,其他的线程可以执行这个对象的另外一个不需要获得这个对象锁的方法。也就是bar().这样能够缩减锁的作用域。从作用在整个对象上变为作用在一个对象上。
3、作用在synchronized(Test.class)
static public class Test { static int counter = 0; static Object testLock = new Object(); public void foo() { synchronized (Test.class) { try { System.out.println("runing bar "+counter++); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void bar() { try { System.out.println("runing bar "+counter++); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } }
public synchronized void bar2() { try { System.out.println("runing bar "+counter++); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } }
这个作用域就更大了,只要是Test的对象。在同一时刻只能有一个获得了锁的对象执行这个方法。这个方法时作用在不同对象之上的。当其中一个对象执行foo()方法之时,他也可以执行bar()方法,因为这个锁是针对Test.class的并非对具体某个对象的锁。当一个对象执行了bar()方法后他就不能执行bar2()方法了。因为public synchronized void bar()的作用域后在这个对象上的。想要执行bar2()需要获取这个对象的锁。
4、synchronized(this)
static public class Test { static int counter = 0; static Object testLock = new Object(); public void foo() { synchronized (this) { try { System.out.println("runing bar "+counter++); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void bar() { try { System.out.println("runing bar "+counter++); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void bar2() { try { System.out.println("runing bar "+counter++); Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } }
这个使用方法其实就跟作用在synchronized是一样的效果。因为都是作用在这个对象上。想要执行里面的其他方法,就必须要获取这个对象的锁。