0、概述
synchronized(lock){ // 访问或修改由该锁保护的共享状态 }
1)synchronized 修饰一般方法,锁是持有该方法的对象的锁,访问同一个类的相同方法时候会互斥。
public synchronized void doSomething(){ // ... }
上代码等价于:
public void doSomething(){ synchronized(this){ // ... } }
2)synchronized 修饰代码块,锁是指定的对象的锁,如果是同一个对象的锁,那么会互斥访问。
// 锁为object对象的锁 synchronized(object){ }
3)synchronized 修饰静态方法,锁是该类Class对象的锁,该类的所有对象访问该类时都会互斥。
public class Demo{ public synchronized static void doSomething(){ // ... } }
上代码等价于:
public class Demo{ public static void doSomething(){ synchronized(Demo.class){ // ... } } }
当某个线程请求一个已经被其他线程持有的锁时,该线程会被阻塞。但是内置锁是可重入的,因此,如果一个内置锁尝试获得已经由他自己持有的锁,那这个请求会立即成功。“重入”意味着获取锁的操作粒度是“线程”而不是”调用“。
重入的实现方法是,为每个所关联一个锁和一个计数值。当计数值为0时,这个锁就被认为是没有被任何线程持有。当线程请求一个未被持有的线程时,JVM记下这个持有者,并且将计数值增1.如果同一个线程再次获得这个锁,计数值将增加,而当线程退出同步代码块时,计数器相应的递减。当计数值为0,这个锁将被释放。
1 public class Test { 2 private Object lock; 3 4 public synchronized void saySomething(){ 5 6 } 7 8 public synchronized void doSomething(){ 9 // 两个函数都是同一个对象锁,可重入 10 saySomething(); 11 } 12 13 public void goSomewhere(){ 14 // 对象锁不一致,不能重入 15 synchronized (lock){ 16 saySomething(); 17 } 18 } 19 }