一个对象对应一把锁,要线程同步需要两者同步为同一对象。在该问题中,synchronized修饰pubulic方法中没有具体的参数默认的锁为this,即是当前实例对象。在创建过程中创建的是两个不同对象,对应两把不同的锁。由于调用时由于用的不是同一个锁,所以不能线程同步。
synchronized修饰的静态方法,能构成线程同步。静态方法加的锁为类对象的锁。由于静态方法具有全局唯一性,调用的时候调用的是同一对象,同一把锁,所以能线程同步。
synchronized修饰代码块有两种锁,一种是对象锁,另外一种是类锁。或者叫实例锁,全局锁。如果采用的是对象锁,需要对象为同一对象才能构成线程同步。如果用的是类锁,而类锁在虚拟机中具有唯一性,自然能构成线程同步。

1. 用在对象

以LOCK 为对象锁了。

当前实例为锁。
对象锁,只有获取当前对象才能进入该方法里面。synchronized methods(){} 与synchronized(this){}之间没有什么区别。

私有锁,在类内部声明一个私有属性如private Object lock,在需要加锁的同步块使用 synchronized(lock)。
使用私有锁可以减小锁的细粒度,减少由锁产生的开销。私有锁其实也是对象锁的一种。
私有锁还可以这样用:用私有锁实现的等待/通知机制。

2. 用在方法里

如果不是单例,同步方法锁将失效。实际上是当前实例作为锁。

静态方法具有全局唯一性,类级别的锁,作为锁线程安全。

3. 用在类里

两个都是类级锁,线程安全。
类锁:使用 synchronized 修饰静态的方法以及 synchronized(class) 同步代码块使用的锁是类锁。
对象锁:使用 synchronized 修饰非静态的方法以及 synchronized(this) 同步代码块使用的锁是对象锁。

类锁和对对象锁不相互阻塞,相同的类锁或相同的实例锁相互阻塞。方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。保证了同一时刻只有一个线程可执行,从而有效的避免了类成员变量的访问冲突。

分类: Java

发表评论

电子邮件地址不会被公开。