一、同步
大多数多线程应用中,两个或两个以上的线程需要共享对同一数据的存取,此时出现多个程序交替处理该数据,从而导致数据出现讹误。
9-1.Synchronized关键字
两种用法: 方法和代码块
方法:方法签名中加入synchronized关键字。
代码块:使用synchronized块对需要进行同步的代码段进行同步。
当它用来修饰一个方法或者一个代码块的时,能够保证在同一时刻最多只有一个线程在执行这段代码
9-1-1 synchronized方法
通过在方法声明中synchronized关键字声明synchronized方法。
(A)当方法是实例方法时,
锁对象是:当前方法所对应的对象本身。
public synchronized void run(){}
(B) 当方法是静态方法
锁对象:是这个类本身
public static synchronized void sd(){}
9-1-2synchronized块
使用同步方法,其同步范围会过大,使用synchronized块,可对方法中的局部代码进行同步处理
synchronized(obj){....}
obj是锁对象,
obj 若为this,则该锁对象是调用该方法的实例。
obj是 class ,则为类锁
9-1-3类锁和对象锁
类锁:锁对象是类,一定会同步。
synchronized(class)和“synchronized修饰静态方法”。
对象锁:
锁对象是实例,只有在单例模式下,锁才能生效
synchronized(obj)和“synchronized修饰非静态方法”
(注意:尽量避免使用静态同步方法,会对性能造成影响)
(注意:对象锁和类锁是互不干预的)
(注意:类锁一定会同步,对象锁只有在单例模式才生效)
9-2.ReentrantLock类
ReentranLock是Lock的实现类,用ReenTranLock类保护代码块
Lock l=new ReentranLock();
l.lock();
try{
//操作
}
finally{
l.unlock()
}
二、Volatile域
A: 一般来说,同步一个方法用synchronized,同步一个数据,用volatile
B: volatile域具有可见性,而不具备原子性。
C: 如果一个域被volatile修饰,那么只要对这个域产生写操作,所有读操作都可以看到这个修改。
D: 原理:
volatile域会被立刻写入主内存;读操作则是在主内存中。
E: 作用:
volatile不能保证线程安全,它只能保护变量安全。主要功能:保护变量不被主函数和中断函数反复修改而造成读写错误。
F: volatile的特性:
保证此变量对所有线程的可见性
禁止指令重排序优化。
G: volatile和synchronized四个不同点
粒度不同: 后者针对对象和类,前者针对变量
syn阻塞: volatile线程不阻塞
syn保证三大特性:原子性,可见性,有序性。 而volatile只保证可见性,有序性。
syn编译器优化,volatile不优化
H:多线程安全读取一个域是三种方法: 1、利用锁; 2、利用volatile域;3、final变量
三、 死锁
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。