前言
顾名思义,同步的意思。当两个线程对一个对象实例进行读写操作的时候,很容易引起读写脏数据、不可重复读、丢失更新的问题。
当代码块被声明了一个Synchronized的时候,就意味着该代码块只能有一个线程能读,其他线程只有等待的状态,等待其他线程读完
才能获得该代码块的执行权,本文以理论理解为主,快速回忆;
正文
第一种方式:同步类中的方法,静态方法和非静态方法。
public synchronized void method() { }
同理,对于静态方法来说,只要加上了synchronized关键字,这个方法就是同步的,
class Test { public static synchronized void method() { } }
第一种方式的特点:
1. synchronized关键字不能继承。
虽然可以使用synchronized来定义方法,但synchronized并不属于方法定义的一部分,因此,synchronized关键字不能被继承。
如果在父类中的某个方法使用了synchronized关键字,而在子类中覆盖了这个方法,在子类中的这个方法默认情况下并不是同步的,
而必须显式地在子类的这个方法中加上synchronized关键字才可以。
2,在定义接口方法时不能使用synchronized关键字。
3. 构造方法不能使用synchronized关键字
4,但大量使用synchronized关键字会造成不必要的资源消耗以及性能损失。
虽然从表面上看synchronized锁定的是一个方法:但实际上synchronized锁定的是一个类。也就是说,如果在非静态方法method1和method2定义时
都使用了synchronized,在method1未执行完之前,method2是不能执行的。静态方法和非静态方法的情况类似。但静态method1和非静态方法method2,
这样就不会互相影响。
如果在类中使用synchronized关键字来定义非静态方法,那将影响这个中的所有使用synchronized关键字定义的非静态方法。如果定义的是静态方法,那么将影响类中所有使用synchronized关键字定义的静态方法。这有点象数据表中的表锁,当修改一条记录时,系统就将整个表都锁住了,因此,大量使用这种同步方式会使程序的性能大幅度下降。
第一种方式:代码块同步:
同步非静态代码块:需要synchronized(this)
public void method() { … … synchronized(this){ … … } }
同步静态代码块:
public class StaticSyncBlock { public static void method1() { synchronized(StaticSyncBlock.class){ … … } } }
特点:在使用synchronized块同步类方法时,非静态方法可以使用this来同步,而静态方法必须使用Class对象来同步。它们互不影响。
当然,也可以在非静态方法中使用Class对象来同步静态方法。但在静态方法中不能使用this来同步非静态方法。
这一点在使用synchronized块同步类方法时应注意。