synchronized锁
我们都知道在jdk 1.5时,synchronized锁是一个重量级锁,缺点如下:
每次获取和释放锁都会带来用户态和内核态的切换,从而增加系统的性能开销 在锁竞争激烈的情况下,synchronized同步锁的性能很糟糕
在JDK 1.5,在单线程重复申请锁的情况下,synchronized锁性能要比Lock的性能差很多
在jdk 1.6时对synchronized进行了优化,大致讲锁分为以下三级
偏向锁
偏向锁指的是如果一个线程重复的获取锁,那么synchronized锁将会是偏向锁,重复获取锁的开销很低,偏向锁也称为递归锁。
轻量级锁
轻量级锁指的是,当前不只一个线程来获取锁,但是获取锁的线程并没有竞争,也就是说两个线程不同时间的获取锁。
重量级锁
重量级锁指的是不仅有多个线程来获取锁,而且多个线程竞争锁。
代码演示轻量级锁的高效
/**
* 查询商品
* @return
*/
public static List<String> query(){
synchronized (map){
try {
List<String> good = map.get("good");
return good;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
200个线程并发请求,处理都是毫秒级的
我们将线程睡一会,尽量让线程去竞争,这个时候轻量级锁就会升级成重量级锁,代码如下:
/**
* 查询商品
* @return
*/
public static List<String> query(){
synchronized (map){
try {
List<String> good = map.get("good");
Thread.sleep(100);
return good;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
同样200个线程并发请求,效果如下,截两张图,越下面竞争越激烈,锁的性能也下降的越快。
最上面的线程
最下面的线程,可以看到原本睡了100毫秒的线程,此时耗时已经接近20秒。
最后想和大家分享一点的是,重量级锁前面还有一级自旋锁,在高并发的场景下我们也可以尝试关闭自旋锁。
-XX:-UseSpinning // 参数关闭自旋锁优化 (默认打开)
-XX:PreBlockSpin // 参数修改默认的自旋次数。JDK1.7 后,去掉此参数,由 jvm 控制
在高并发的场景下,我们也可以使用读写锁来进行提高性能,代码如下:
public class ReadAndWriteLockGoodsCache {
private static final Map<String, List<String>> map = new HashMap<>();
private static ReadWriteLock lock = new ReentrantReadWriteLock();
/**
* 更新商品
* @param goodList
*/
public static void add(String goodList){
Lock writeLock = lock.writeLock();
writeLock.lock();
List<String> good = map.get("good");
if(good == null){
good = new ArrayList<>();
}
good.addAll(Arrays.asList(goodList.split(",")));
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put("good",good);
writeLock.unlock();
}
/**
* 查询商品
* @return
*/
public static List<String> query() {
Lock readLock = lock.readLock();
readLock.lock();
List<String> good = map.get("good");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
readLock.unlock();
return good;
}
}
由于读锁是共享锁,并不存在竞争关系,而写锁是独占锁,可以保证同步,同样200个线程压测读取数据,效果如下:
可以看出基本没有竞争锁的开销。
最后
关于并发其实东西还是挺多的,只要一点一点的搞清楚其实并没有想象的那么难,不积硅步无以至千里。