1.Java中的每个对象都可以作为锁。
2.普通同步方法,锁是当前实例对象。
3.静态同步方法,锁是当前类的class对象。
4.同步代码块,锁是括号中的对象。
5.当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
6.方法内的变量为线程安全:方法中的变量不存在非线程安全问题,永远都是线程安全的,这是因为方法内部的变量是私有的特性造成的
7.两个线程分别访问同一个类的两个不同实例的相同名称的同步方法,效果却是以异步的方式运行的。关键字synchronized取得的锁都是对象锁,而不是把一段代码或方法当作锁,哪个线程先执行带synchronized关键字的方法,哪个线程就持有该方法所属对象的锁Lock,那么其他线程只能呈等待状态,前提是多个线程访问的是同一个对象。但如果多个线程访问多个对象,则JVM会创建多个锁
8.调用用关键字synchronized声明的方法一定是排队运行的,另外需要牢牢记住“共享”这两个字,只有共享资源的读写访问才需要同步化,如果不是共享资源,那么根本就没有同步的必要。
9.两个线程A、B访问同一个对象object的两个不同的方法(一个同步方法,一个普通方法),虽然A线程持有了object对象的Lock锁,但是B线程完全可以异步调用非synchronized类型的方法。
10.synchronized拥有锁重入的功能,也就是在使用synchronized时,当一个线程得到一个对象锁后,再次请求此对象锁时是可以再次得到该对象的锁的,这也证明了在一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远可以得到锁的。“可重入锁”的概念是:自己可以再次获取自己的内部锁,比如有一条线程获取了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁的时候还是可以获取的,如果不可锁重入的话,就会造成死锁。可重入锁也支持在父子类继承的环境中。当存在父子类继承关系时,子类是完全可以通过“可重入锁”调用父类的同步方法的。
11.同步不可以继承。同步不能继承,子类重写父类的同步方法不具有同步性,所以还得在子类的方法中添加synchronized关键字。
12.当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码块的访问将被阻塞。
13.和synchronized方法一样,synchronized(this)代码块也是锁定当前对象的。
14.锁非this对象具有一定的优点:如果在一个类中有很多个synchronized方法,这时虽然能实现同步,但会受到阻塞,所以影响运行效率,但如果使用同步代码块锁非this对象,则synchronized(非 this)代码块中的程序与同步方法是异步的,不与其他锁this同步方法争抢this锁,则可大大提高运行效率。
15.“synchronized(非 this 对象 X)”格式的写法是将X对象本身作为“对象监视器”,这样就可以得出3个结论:
当多个线程同时执行synchronized(X){}同步代码块时呈同步效果。
当其他线程执行X对象中synchronized同步方法时呈同步效果。
当其他线程执行X对象方法里面的synchronized(this)代码块时呈同步效果。
16. synchronized加到static静态方法上是给Class类上锁,而它加到非static静态方法上是给对象上锁。示例运行结果异步的原因是持有不同的锁,一个是对象锁,另外一个是Class锁,而Class锁可以对类的所有对象实例起作用。同步synchronized(class)代码块的作用和synchronized static 方法的作用一样。
17.在JVM中具有String常量池缓存的功能,同步synchronized代码块都不使用String作为锁对象,而改用其他,比如new Object()实例化一个Object对象,但它并不放入缓存中。
18.在将任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,如果同时持有相同的锁对象,则这些线程之间就是同步的,如果分别获得锁对象,这些线程之间就是异步的。只要对象不变,即使对象的属性被改变,运行结果还是同步的。