一、synchronized同步方法
1.非线程安全问题会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是“脏读”,也就是读取到的数据已经被修改过。而线程安全是指获得实例变量的值是经过同步处理的,不会出现脏读的现象。
2、非线程安全问题存在于实例变量中,对于方法内部的私有变量,不存在非线程问题。
3、synchronized用于保障原子性、可见性和有序性。
二、synchronized原理
1、在方法中使用synchronized关键字实现同步的原因是因为使用了flag标记ACC_SYNCHRONIZED,当调用方法时,调用指令会检查方法的ACC_SYNCHRONIZED访问标志是否设置。如果设置了,执行线程先持有同步锁,然后执行方法,最后在方法完成时释放锁。
2、synchronized获取的锁是对象锁。
3、只有共享资源的读写访问才需要同步化,如果不是共享资源,那么就没有同步的必要。
三、锁重 入功能
1、synchronized拥有重入锁的功能,即在使用synchronized时,当一个线程得到一个对象锁后,再次请求此对象锁时是可以得到该对象锁的,这也证明了synchronized方法/块的内部调用本类的其他synchronized方法/块时,可以得到锁。
2、锁重入支持继承环境。子类与父类可以公用同一个对象锁。
3、当一个线程中的锁出现异常时,其所持有的锁会自动释放。
四、synchronized同步语句块
1.synchronized方法的弊端
若当前线程调用的同步方法执行一个长时间的任务,那么其他线程必须等待当前线程执行完之后,继续执行。
2.synchronized方法将当前对象作为锁,而synchronized代码块将任意对象作为锁。可以将锁看成一个标识,哪个线程持有这个标识,就可以执行同步方法。
3.synchronized同步代码块的使用
当两个并发线程访问用一个对象object中的synchronized(this)同步代码块时,一段时间内只能有一个线程得到执行,另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象的非synchronized(this)同步代码块。
4.synchronized代码块间的同步性
在使用同步synchronized(this)代码块时需要注意,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码块的访问将被阻塞,这说明synchronized使用的对象监视器是同一个,即使用的锁是同一个。
5.多个线程调用同一个对象中的不同名称的synchronized同步方法或synchronized(this)同步代码块时,调用的效果是按顺序执行,即同步。
6.同步代码块放在非同步synchronized方法中进行声明,并不能保证调用方法的线程的执行同步,也就是线程调用方法的顺序是无序的,虽然在同步块中执行的顺序是同步的。
7.synchronized可以应用在static静态方法上,这种情况是将Class对象作为锁。synchronized(class)代码块可以对类的所有实例起作用。
四、volatile
1.volatile的特性:
可见性:B线程能马上看到A线程更改的数据。
原子性和禁止代码重排序
2.volatile作用:强制线程从共有堆栈取值。
3.synchronized具有可见性,能够使线程工作内存中的私有变量与公共内存中的变量进行同步。
4.i++非原子性的原因
i++操作的步骤分为一下三步:
1).从内存中取值。
2).计算i的值。
3).将i的值写道内存中。
5.i++实现原子性的方法
1)使用synchronized关键字。
2)使用Atomic原子类实现i++操作的原子性