一、内置锁
每个Java对象都可以用做一个实现同步的互斥锁,这些锁被称为内置锁。线程进入同步代码块或方法时自动获得内置锁,退出同步代码块或方法时自动释放该内置锁。进入同步代码块或者同步方法是获得内置锁的唯一途径。
二、实例同步方法
synchronized用于修饰实例方法(非静态方法)时,执行该方法需要获得的是该类实例对象的内置锁(同一个类的不同实例拥有不同的内置锁)。如果多个实例方法都被synchronized修饰,则当多个线程调用同一实例的不同同步方法(或者同一方法)时,需要竞争锁。但当调用的是不同实例的方法时,并不需要竞争锁。
三、静态同步方法
synchronized用于修饰静态方法时,执行该方法需要获得的是该类的class对象的内置锁(一个类只有唯一一个class对象)。调用同一个类的不同静态同步方法时会产生锁竞争。
四、同步代码块
synchronized用于修饰代码块时,进入同步代码块需要获得synchronized关键字后面括号内的对象(可以是实例对象也可以是class对象)的内置锁。
五、synchronized使用总结
锁的使用是为了操作临界资源的正确性,而往往一个方法中并非所有的代码都操作临界资源。换句话说,方法中的代码往往并不都需要同步。此时建议不使用同步方法,而使用同步代码块,只对操作临界资源的代码,也即需要同步的代码加锁。这样做的好处是,当一个线程在执行同步代码块时,其它线程仍然可以执行该方法内同步代码块以外的部分,充分发挥多线程并发的优势,从而相较于同步整个方法而言提升性能。
释放Java内置锁的唯一方式是synchronized方法或者代码块执行结束。若某一线程在synchronized方法或代码块内发生死锁,则对应的内置锁无法释放,其它线程也无法获取该内置锁(即进入跟该内置锁相关的synchronized方法或者代码块)。
这里有一点不明确,调用wait不就可以释放锁吗?待验证