非线程安全:在多个线程对同一个对象中的实例进行并发访问时发生,产生的后果即为脏读。java
线程安全:得到的实例变量的值是通过同步处理的,不会出现脏读现象。安全
非线程安全问题存在于实例变量中,即共享的变量 ,但如果方法内部的私有变量,则不存在非线程安全问题。这是由于方法内部的变量是私有的特性形成的。并发
若是多个线程同时访问一个对象中的实例变量,则有可能出现非线程安全问题。异步
解决方法:在方法前加关键字synchronized便可。在两个线程访问同一个对象中的同步方法时必定是线程安全的。jvm
多个对象多个锁。关键字synchronized取得的锁都是对象锁,那个线程先访问带synchronized关键字的方法,那个线程就持有该方法所属对象的锁Lock,那么其余线程就只能处于等待状态,前提是多个线程访问的是同一个对象。ide
Service service = new Service(); Thread t1 = new Thread(service); Thread t2 = new Thread(service); t1.start(); t2.start();
但如果多个线程访问多个对象,则jvm就会建立多个锁,则运行结果就是异步的。线程
Service service1 = new Service(); Service service2 = new Service(); Thread t1 = new Thread(service1); Thread t2 = new Thread(service2); t1.start(); t2.start();
若A线程先持有object对象的Lock锁,B线程能够以异步的方式调用object对象中的非synchronized方法。code
若A线程先持有object对象的Lock锁,B线程若是要调用object对象中的synchronized方法则需等待,也就是同步。对象
脏读:在读取实例变量时,此值已经被其余线程更改过了。继承
synchronized锁重入:在使用synchronized关键字时,当一个线程获得一个对象锁后,再次请求此对象锁时是能够再次获得该对象的锁的。即在一个synchronized方法/块的内部调用本类的其余synchronized方法/块时,是永远能够获得锁的。
public class Service{ public synchronized methodA(){ methodB(); } public synchronized methodB(){ } }
线程会同步调用methodA--methodB的顺序。
可重入锁:本身能够再次获取本身的内部锁。
可重入锁也支持在父子类继承的环境中。当存在父子类继承关系是,子类是彻底能够经过可重入锁的方式调用父类的同步方法。
当一个线程执行的代码出现异常时,其所持有的锁会自动释放。
同步不具备继承性。因此override父类的synchronized方法仍须要加上synchronized关键字。