Synchronized用法
Synchronized关键字主要用在多线程并发时共享资源竞争的问题。当执行被synchronized关键字保护的代码片段时,将检查锁是否可用,若锁可用,则获取锁,执行代码,释放锁。 –《Java编程思想》
Synchronized的可以修饰类,方法,静态方法以及代码块。
1 | class Test { |
在修饰方法和代码块时,获得是对象锁;而修饰类和静态方法(属于类而不属于对象)时,获得是类锁。
1 | Test test1 = new Test(); |
接下来说明对象锁和类锁的区别:
顾名思义,对象锁的作用对象是针对单个对象的:在不同的线程执行test1.fun1()
和test2.fun1()
,二者是互不干扰的。另外,同个对象的对象锁是互斥的,在不同线程执行test1.func1()
和test1.func5()
,需等test1.func1()
执行完毕释放test1
的对象锁,test1.func5()
拿到锁后才能执行。
而类锁的作用对象是整个类,在不同的线程执行test1.fun4()
和test2.fun4()
是互斥的,必须先等test1.fun4()
执行完毕,释放类锁,test2.fun4()
才能执行。同理test1.fun3()
和test2.fun3()
也是一样,因为使用synchronized修饰静态方法,拿到的也是类锁。
综上所述,可以得出结论:
- 同对象的对象锁是互斥的,不同对象的对象锁是非互斥的,对象锁和类锁也是非互斥的。
- 因为同步对运行效率有影响,因此尽量是用同步代码块越小越好,即尽量使用synchronized*(this)来同步一块代码,而不是直接修饰一整个方法。
- synchronized关键字是不能继承的。若子类覆盖了父类的synchronized方法,默认是没有同步的。
- 构造方法不能使用synchronized关键字,但是可以使用synchronized代码块来进行同步.
- 在定义接口方法时不能使用synchronized关键字。