synchronized关键字的用法详解:
第一个用法:对象锁
代码块形式:手动指定锁对象;
Object lock1 = new Object(); Object lock2 = new Object(); @Override public void run() { synchronized (lock1) { System.out.print("线程:" + Thread.currentThread().getName() + "的lock1开始啦 "); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print("线程:" + Thread.currentThread().getName() + "的lock1结束啦 "); } synchronized (lock2) { System.out.print("线程:" + Thread.currentThread().getName() + "的lock2开始啦 "); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print("线程:" + Thread.currentThread().getName() + "的lock2结束啦 "); } }
方法锁形式:synchronized修饰普通的方法,锁对象默认为this;
public synchronized void method(){ System.out.print("线程:" + Thread.currentThread().getName() + "的lock1开始啦 "); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print("线程:" + Thread.currentThread().getName() + "的lock1结束啦 "); } public void run() { method(); }
第二个用法:类锁
java类有很多个对象,但是只有一个类(class), 类锁即是class对象的锁。
形式1:static 方法加锁;
@Override public void run() { method(); } //类锁1 static synchronized void method(){ System.out.print("线程:" + Thread.currentThread().getName() + "的类锁1开始啦 "); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print("线程:" + Thread.currentThread().getName() + "的类锁1结束啦 "); }
形式2:synchronized(*.class);
@Override public void run() { synchronized (SynchronizedRequest2.class){ System.out.print("线程:" + Thread.currentThread().getName() + "的类锁1开始啦 "); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.print("线程:" + Thread.currentThread().getName() + "的类锁1结束啦 "); } }
对象锁是实例级别的锁,所以在测试类中,只要使用同一个类的单例runnable就可以让线程1和线程2串行化执行;
类锁是类级别的锁,所以在测试类中,需要检验的是同一个类的不同实例。
可重入性:
锁的可重入性质是线程级别的,与对象无关。无论是递归,两个同步方法,继承类的重写同步方法,都可以重入。