前一段时间一直在加班加点的研究新技术,研究新语言,以至于两个月没更新博客、总结知识,能坚持果然不容易
前一段时间一直在做一个日志消息发送的功能组件,最终被打成单独jar包引用,其中涉及到大量的线程安全问题,头一次这么深入的去研究线程,有些手足无措,最终还是按照需求做了出来,以此记录总结遇到的问题
线程锁优化问题
public static synchronized int cleanDate(int type) {
if (type == 0) {
sysThread.exit = false;
int num = httpPost(sysLogDataList);
sysLogDataList = Collections.synchronizedList(new ArrayList<>());
dataMap = new HashMap<>();
return num;
} else {
apiThread.exit = false;
int num = httpPost(apiLogDataList);
apiLogDataList = Collections.synchronizedList(new ArrayList<>());
return num;
}
}
如上代码,在方法中加入synchronized关键字修饰,可以保证同一时间只有一个线程能访问该方法(单例模式下),这样虽然实现了线程安全的保证,但是由于该方法中操作了两个对象sysLogDataList和apiLogDataList,并且两个对象肯定不会被同时操作,这样就会导致其它不涉及到操作同一对象的线程也会处于等待状态,造成阻塞,降低程序效率,因此将代码进行优化成下面部分
public static int cleanDate(int type) {
if (type == 0) {
synchronized (sysLogDataList) {
sysThread.exit = false;
int num = httpPost(sysLogDataList);
sysLogDataList = Collections.synchronizedList(new ArrayList<>());
dataMap = new HashMap<>();
return num;
}
} else {
synchronized (apiLogDataList) {
apiThread.exit = false;
int num = httpPost(apiLogDataList);
apiLogDataList = Collections.synchronizedList(new ArrayList<>());
return num;
}
}
}
这样只有在操作该对象时才会被锁,操作其它对象依然可以进入该方法,这就是降低锁粒度。
举个简单的例子,去KTV唱歌时我们都会关包间的房门,防止其他人打扰,但是我们没必要将整个KTV锁住,导致其它顾客不能正常去其它包间,导致资源浪费