synchronized用法
synchronized修饰的对象有几种:
修饰一个类:其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象;
修饰一个方法:被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
修饰一个静态的方法:其作用的范围是整个方法,作用的对象是这个类的所有对象;
修饰一个代码块:被修饰的代码块称为同步语句块,其作用范围是大括号{}括起来的代码块,作用的对象是调用这个代码块的对象;
修饰一个类
其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象,如下代码:
class ClassName {
public void method() {
synchronized(ClassName.class) {
// todo
}
}
}
修饰一个方法
synchronized 修饰一个方法很简单,就是在方法的前面加synchronized,例如:
public synchronized void method()
{
// todo
}
另外,有几点需要注意:
在定义接口方法时不能使用synchronized关键字。
构造方法不能使用synchronized关键字,但可以使用synchronized代码块来进行同步。
synchronized 关键字不能被继承 。如果子类覆盖了父类的 被 synchronized 关键字修饰的方法,那么子类的该方法只要没有 synchronized 关键字,那么就默认没有同步,也就是说,不能继承父类的 synchronized。
修饰静态方法
我们知道 静态方法是属于类的而不属于对象的 。同样的, synchronized修饰的静态方法锁定的是这个类的所有对象 。如下:
public synchronized static void method() {
// todo
}
修饰代码块
当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
以上规则对其它对象锁同样适用.
ps
修饰静态方法其实是类锁,区别于对象锁。
public ClassA {
public synchronized static void staticMethod() {
// todo
}
public synchronized void method() {
// todo
}
public void method2() {
synchronized(ClassA.class) {
// todo
}
}
}
ClassA obj = new ClassA();
也就是说ClassA.staticMethod() 和 obj.method() 并不会存在互斥关系,但是会和obj.method2()存在互斥关系。
pps
在平时多线程的使用中,特别是关于自己定义一些东西的遍历和添加的时候,最好保证在遍历的时候不要添加,在输出数据的同时不要添加数据,因为多线程机智,你无法控制输出输入在同一个线程的话,最好使用锁机制,来避免一些错误的产生。