关于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.注意一下线程可见性的问题
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值