概述
在多线程编程中,当存在资源竞争时,多线程环境就可能会导致程序的结果是一个非预期结果,也称之为程序是非线程安全的。
public Test{
private int i;
public void add(){
i++;
}
public int get(){
return i;
}
}
上面这段代码在多线程环境下,线程之间存在成员变量i的竞争关系。当一个线程调用add方法时,另外一个线程也调用了add方法,可是此时两个线程对i的修改是彼此不可见的。因为线程之间没有实现通信(一个线程对i的修改对于其他所有线程都是可见的),所有导致了最终结果发生异常。
synchronized锁
Java中的锁是用来控制多个线程访问共享资源的方式,分为阻塞型锁和非阻塞性锁。阻塞型锁的代表就是synchronized,synchronized可以同步代码块、同步方法、同步类。synchronize的机制是阻塞性机制,也就是同一时刻只会有一个线程获得锁执行synchronize同步部分。synchronize是非公平锁,即每次获得锁的操作是不考虑请求顺序的先后的。
其他线程想要执行同步部分,必须先阻塞,等待获得锁的线程释放锁之后,再去竞争获得锁。
public Test{
private int i;
public void add(){
synchronize(this){
i++;
}
}
public int get(){
return i;
}
}
上述代码对i++操作进行同步,也就意味着同一时刻只会有一个线程对i进行修改。其他线程想要修改i必须竞争获得锁才能执行i++。
优点
synchronize是jvm自身特性,较新版本的jvm对synchronize做了较多的优化。并且synchronize会自动释放锁,从而不会因为锁未释放而导致的死锁现象。
缺点
synchronize是阻塞性锁,线程的阻塞会引起cpu对线程的调度,效率会降低。synchronize不可中断,一旦获得锁之后必须要将同步部分执行完之后才会释放锁。synchronize在高并发环境下并不适用。
Lock接口
ReentrantLock 是 java.util.concurrent(J.U.C)包中的锁,ReentrantLock 是jdk实现的。
public class LockExample {
private Lock lock = new ReentrantLock();
public void func() {
lock.lock();
try {
for (int i = 0; i < 10; i++) {
System.out.print(i + " ");
}
} finally {
lock.unlock(); // 确保释放锁,从而避免发生死锁。
}
}
}
使用ReentrantLock一定要有锁释放操作,否则有可能引起死锁。
内存模型的三大特性
原子性
Java 内存模型保证了 read、load、use、assign、store、write、lock 和 unlock 操作具有原子性。例如对一个int型变量赋值的过程就是原子性的。本人对于原子性的理解就是这个操作不能再被分解成更单位化的操作就称这个操作具有原子性。
例如:
int a = 1;
这个操作不能被分解
a++;
对于a++这个操作,它是分两步的,第一先读取a的值,第二步是将a + 1的值赋给a。所以这个操作不是一个原子性的操作。
有序性
Java内存模型保证在同一线程观察,所以操作都是有序的。但是放在线程环境下就是不能保证了。
可见性
可见性指当一个线程修改了共享变量的值,其它线程能够立即得知这个修改。Java 内存模型是通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值来实现可见性的。
volatile关键字只能保证对变量的读写操作的有序性和变量的可见性,它不能保证变量操作的原则性。例如 volatile int a; a++;这个操作就不是原子性的操作。
CAS
CAS是一种乐观并发策略,属于非阻塞同步。先进行操作,如果没有其它线程争用共享数据,那操作就成功了,否则采取补偿措施(不断地重试,直到成功为止)。
CAS即比较并交换,CAS操作一般都会有一个旧预期值和新值,当内存中的值等于预期值时,才会将内存值更新为新值。CAS代码一般都是一个死循环,当满足上述条件时才会退出循环。
CAS操作存在的问题:
- ABA问题
当一个变量初始读取的值是A,然后被修改成B,最后又被修改回A。这对于CAS操作来说对于这个变量是没有发生修改的。可以加入版本号来解决ABA问题,不过ABA问题一般不会影响程序的执行。 - 循环时间长,开销大
如果一个CAS操作一直不成功,对于CPU的开销是巨大的。 - 只能保证一个共享变量的原子操作
对多个变量操作时,CAS无法保证操作的原子性