方法内的局部变量是线程安全的,不存在线程不安全的问题,类和对象内部的实例变量存在线程不安全的问题。
synchronized同步方法:
1.线程A获取了对象Object的某个synchronized锁时,其他线程需等待线程A释放该锁才能访问该锁修饰的那段代码(方法、变量等),但是其他线程可以异步访问对象Object的其他非synchronized方法。
2.synchronized支持锁重入:线程A获得了对象Object的一个对象锁之后,可以再获得该对象的对象锁,即该线程在该对象的一个synchronized方法/块内部访问其他synchronized方法/块是永远可以获得锁的。
3.当一个线程的代码出现异常时,其所持有的所有锁会自动释放。
4.同步不具有继承性,子类要想确保从父类继承过来的synchronized方法/块的同步则还需要在调用的方法/代码块前添加synchronized关键字。
5.synchronized修饰static静态方法时,是对类进行加锁;synchronzied(某类.Class)修饰的方法/块也是对类进行加锁。
6.synchronzied和synchronzied(this)修饰的方法/块是对对象进行加锁。
7.要避免死锁问题:避免双方互相持有对方的锁的情况发生。
volatile同步方法:
1.原理:线程直接从系统主存中读写变量比较浪费时间和资源,因此每个线程都会有自己的工作内存,将变量拷贝到工作内存中,对其进行访问和修改,最终再将其写入主存中。这样对于主存中的同一个变量,每个线程在自己的工作内存中都有一份拷贝,各线程在自己工作内存中对该变量的操作对于其他线程来说是不可见的。而使用了volatile关键字修饰变量后,会强制使每个访问该变量的线程从主存中读取该变量进行操作,然后再写入主存中。2.volatile修饰变量提高了该变量在多个线程间的可见性,但并没有保证各线程对该变量进行操作的原子性,即线程A读取了该变量后,还未操作完,其他线程还可以读取该变量并进行操作。
synchronized和volatile关键字的比较:
1.synchronized关键字可以修饰变量、方法以及代码块,而volatile关键字只能修饰变量。
2.volatile只能保证数据在多个线程间的可见性,但不能保证原子性,synchronized关键字能保证原子性(也可以间接保证可见性)。即synchronized关键字可以保证各个线程之间访问资源的同步性,而volatile关键字不可以。