Synchronized 简述
- 编写一个类时或者方法、码块时,如果其中的代码可能运行于多线程环境下,那么就要考虑同步的问题
- Java中内置了语言级的同步关键字-synchronized,这大大简化了Java中多线程同步的使用
- synchronized 是Java中的关键字,是一种同步锁,注意用于修饰方法、代码块
- 例如用Account类表示一个银行账户信息,主程序中生成100个线程,再启动它们,每一个线程都对此账户存100元,然后又取出100元。最终账户的余额应该还是1000元。如果线程不同步,则运行的结果极可能超出我们的想像
注意事项
- synchronized关键字不能继承
- synchronized 可以定义方法,但synchronized并不属于方法定义的一部分,因此synchronized关键字不能被继承。
- 如果在父类中的某个方法使用了synchronized关键字,而在子类中覆盖了这个方法,在子类中的这个方法默认情况下并不是同步的,而必须显式地在子类的这个方法中加上synchronized关键字才可以。
- 当然可以在子类方法中调用父类中相应的方法,这样虽然子类中的方法不是同步的,但子类调用了父类的同步方法,因此,子类的方法也就相当于同步了。
- 定义接口方法时不能使用synchronized关键字
- 构造方法不能使用synchronized关键字,但可以使用synchronized代码块来进行同步
修饰代码块
- 被修饰的代码块称为同步代码块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象,对不同线程中的同一对象有效——对象锁;
synchronized this 对象锁
- synchronized(this) 与下面"修饰普通方法"效果完全一致
- 如下所示:synchronized(this)是对象锁,可以同步不同线程中的同一个对象,下面能达到同步的目的
- 如下所示:不同线程中对象不同,sysnchronized(this)是无法同步的。
- 线程thread1执行的是第一个匿名对象中的synchronized代码,而线程thread2执行的是第二个匿名对象中的synchronized代码,而 synchronized锁定的是对象,这时会有两把锁分别锁定第一个匿名对象和第二个匿名对象,而这两把锁是互不干扰的,不形成互斥,所以两个线程可以同时执行。
synchronized Class 类锁
- 作用的范围是synchronized(Class) 后面括号括起来的部分,作用的对象是这个类的所有对象——类锁。
修饰普通方法 对象锁
- 这里所说的"普通方法"是指"非静态方法"
- 被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象,对不同线程中的同一对象有效————对象锁;
一个线程访问一个对象的synchronized(this){}代码块、或synchronized方法时,别的线程可以访问该对象的非synchronized代码块和方法而不受阻塞。
- 一个线程访问一个对象的synchronized(this){}代码块、或synchronized方法时,别的线程不可以访问该对象的其它synchronized代码块和方法。
同一对象
不同对象
修饰静态方法 类锁
- 作用的是整个静态方法,作用的对象是这个类的所有对象——类锁;
- 静态方法是属于类的而不属于对象的,同样synchronized修饰的静态方法锁定的是这个类的所有对象。