优化多线程
优化线程多线程程序时,我们可以通过减少竞争的方式来优化多线程程序的运行。
发生锁竞争的主要原因
1、锁的请求频率
2、持有锁的时间过长
如果两者的乘积很小,那么大多数获取锁的操作都不会发生竞争。对可升缩性不会造成影响。如果锁的请求量很频繁,持有锁的时间一旦较长,其他线程进入线程阻塞等待获取锁,会有大量的任务等待完成。在极端情况下会出现大量工作等待完成而处理器闲置的情况。
优化方法
有三种减少线程竞争的方法:
a、减少锁持有的时间
b、降低锁请求的频率
c、使用带有协调机制的独占锁(这些机制允许更高的并发性)
具体的优化技术
1、减小锁的范围(快进快出)
缩小锁的范围就是指在写代码是不需要将整个方法进行加锁,因对需要加锁的情况进行分析,将需要加锁的操作进行加锁。比如我们现在需要进行三种操作,但是真正需要加锁的只是第二种操作,但是对于很多人编程来看,就将整个三种操作进行加锁了。
问题代码
public synchronize void do(){
do1();
do2();
do3();
}
优化后的代码
public synchronize void do(){
do1();
synchronized(this){
do2();
}
do3();
}
2、减小锁的粒度
减小锁的粒度指的就是明确自己需要加锁的对象,比如对于电影院买票的场景来说,买票与买吃的是分别的两个队伍,如果我们不区分的话,那么所有的人都必须在这一列来排队,因此会发现非常的拥堵,但是如果分成了两对,买票的一队,买零食的一对,那么就会速度相对于快很多。
问题代码
Object d1 = new Object();
Object d2 = new Object();
public void buyFood(){
synchronized(this){
buyF();
}
}
public void buyTicket(){
synchronized(this){
buyT();
}
}
优化后的代码
Object d1 = new Object();
Object d2 = new Object();
public void buyFood(){
synchronized(d1){
buyF();
}
}
public void buyTicket(){
synchronized(d2){
buyT();
}
}
3、锁分段
分段锁就是将假设在一个只有一个队列的时候,人为的将这个队列分成多个小队列,然后当有新的人需要进入排队的时候就有8个选择了,同时来两个人的时候就不要等第一个人站好后才进去,可以选择不同的小队伍了。
具体的例子我就不写了,可以去了解下ConcurrentHashMap就行,他基本上就是一个分段锁的良好实现。