当前位置: 首页 > Java > 正文

cpu sy高排查的case(一)

1 星2 星3 星4 星5 星 (2 次投票, 评分: 5.00, 总分: 5)
Loading ... Loading ...
baidu_share

前几天碰到了一起cpu sy高的case,当时cpu的sy已经跑到了80%左右,cpu sy基本都是上下文切换多造成的,于是dump下线程堆栈,看看都在做什么,看到线程堆栈里一大堆线程的在Thread.yield这步,这就很容易理解为什么cpu sy跑到那么高了。

于是翻查了下堆栈对应的代码,代码类似如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public long next(){
    while (!this.readyFlag.get()){
      Thread.yield();
    }
 
    long m = this.max.get();
    long rtn = this.idGenerator.next();
 
    if (rtn > m) {
 
        ...
 
        this.readyFlag.set(false);
 
        ...
 
        this.readyFlag.set(true);
 
        return next();
    }
    return rtn;
}

看到这段代码实在是想吐槽…无非就是想在有线程做rtn > m中间的动作时,其他进入next()的代码就等在最开始,竟然用Thread.yield这种方式,介个…

这段代码如果我写呢,会去掉readyFlag,改成用ReentrantReadWriteLock,rtn > m中用WriteLock,外面用ReadLock,这样可以避免当代码进入到rtn > m后,要通过Thread.yield这样的方式去等到readyFlag变成true。

感兴趣的也可以用下面的代码去跑跑,可以立刻看到cpu sy high起来…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Spike {
 
    public static void main(String[] args) throws Exception{
        new Spike().go();
    }
 
    public void go(){
        for (int i = 0; i < 200; i++) {
            new Thread(new Yield()).start();
        }
    }
 
    class Yield implements Runnable{
 
        public void run() {
            while(true){
                Thread.yield();
                try {
                    Thread.sleep(1);
                } 
                catch (InterruptedException e) {
                    // IGNORE
                }
            }   
        }
 
    }

本文固定链接: http://www.chepoo.com/cpu-sy-high-case-one.html | IT技术精华网

cpu sy高排查的case(一):等您坐沙发呢!

发表评论