关于java hotspot vm的server版和client版的一点小事

我们知道,java的虚拟器其实是有两个版本的,

client版比较适合桌面程序,它会做一些例如像快速初始化,懒加载这一类的事情来适应桌面程序的特点

server版则比较适合服务器程序,它做的则是一些针对服务器特点的事情,比如预加载,尤其在一些并发的处理上,它更是会做很多的优化,

比如线程共享变量的处理,它经过编译(运行)发现并没有要求某一变量对其他线程可见,它则不会将该变量同步到主存(可能永远不会)


之前在学习java并发时写过一个线程池

http://snake1987.iteye.com/blog/993112

稍微试了一下-server跟-client的区别

下面是运行结果
//-client
//55234043228
//234164019238
//-server
//3076884002
//3077230620

第一个结果是调度任务完成时间

第二个结果是完成所有任务的完成时间

很吓人的结果 近10倍

然后是今天

最近在写一个模块,并发会很高,所以打算能避免冲突则尽量让它不冲突

所以在一个全局消息队列的处理上,只在修改时加锁,在读取时则不加锁

因为消息的读取在业务上是允许延时的,所以打算不保证可见性,

因为根据文档得知cpu寄存器在一段时间后,是会将数据同步到主存的,这时自然就可见了

但会不会同步到主存呢,为了验证这个问题,写了个小测试
public static class LoopWrap {

        private boolean loop;

        public LoopWrap(boolean loop) {
		this.loop = loop;  
	}

        public boolean isLoop() {  
		return loop;  
	}

        public void setLoop(boolean loop) {
		this.loop = loop; 
	}

    }

    public static void main(String[] args) throws InterruptedException {
        //该变量没有保证可见性
        LoopWrap loop = new LoopWrap(true);

        for(int i = 0;i<3;i++) {  
		Thread t = new TestThread(loop);  t.start();  
	}
        System.out.println("sleep");
        Thread.sleep(10000);
        System.out.println("change loop");
	//sleep之后改变变量为false,如果是可见的,线程应该马上输出end,如果没有,则看一下什么时候会可见
        loop.setLoop(false);

       	Thread.sleep(10000);
    }

    public static class TestThread extends Thread {

        private LoopWrap loop;

        public TestThread(LoopWrap loop) {  
		this.loop = loop;  
	}

        @Override
        public void run() {
            long count = 0;
            while(loop.isLoop()) {
                for(int i = 0;i<100;i++) {  
			count+=i;  
		}
            }
            System.out.println("end");
        }
    }
	public static class LoopWrap {
        	private boolean loop;

        	public LoopWrap(boolean loop) {  
			this.loop = loop; 
		}
        	public boolean isLoop() { 
			return loop;  
		}
        	public void setLoop(boolean loop) { 
			this.loop = loop; 
		}
    	}

    	public static void main(String[] args) throws InterruptedException {

        LoopWrap loop = new LoopWrap(true);

        for(int i = 0;i<3;i++) {  
		Thread t = new TestThread(loop);
		t.start();  
	}
        System.out.println("sleep");
        Thread.sleep(10000);
        System.out.println("change loop");
        loop.setLoop(false);

        Thread.sleep(10000);

    }

    public static class TestThread extends Thread {

        private LoopWrap loop;

        public TestThread(LoopWrap loop) {  
		this.loop = loop;  
	}

        @Override
        public void run() {
            long count = 0;
            while(loop.isLoop()) {
                for(int i = 0;i<100;i++) {  
			count+=i;  
		}
            }

            System.out.println("end");
        }

    }


-client下是瞬间输出了end

-server下是死循环~~也就是说一直没有同步到主存了,或者说其他的线程一直只访问的是线程内缓存,也没有重新从主存中去取值

在这说一下,在开发并发相关的tx们,注意一下
1.在做压力测试的时候,记得使用hotspot的server版,否则是没有意义的

2.注意一下线程可见性的问题

猜你喜欢

转载自snake1987.iteye.com/blog/1670484