JMM对多线程的一些约束

多线程存在的问题

1.所见非所得
2.无法肉眼去检测程序的准确性。
3.不同的运行平台有不同的表现
4.错误难以重现。

典型代码
public class Demo{
	int i = 0;
	boolean isRunning = true;
   public static void main(String[] args){
  	Demo demo = new Demo();
  	new Thread(){
		public void run(){
	 	while(isRunning){
	 		demo.i++;
	 	}
	 	System.out.println(demo.i);
	 	}
		}
		Thread.sleep(30000);
		isRunning = false;
		System.out.println("shutdown");
  }
}

代码在jdk32位和64位的server和client运行结果不同。

原因
jdk32位server和jdk64位会进行指令优化,将isRunning缓存为true变为
if(isRunning){
	while(true){
	}
}
可见性问题原因

1.cpu的高速缓存机制
2.java虚拟机对代码的优化。
java编程语言的语义允许Java编译器和微处理器进行执行优化。,这些优化导致了与代码不在同步,从而导致看似矛盾的行为。

解决

在java内存模型中规定:

使用volatile,修饰的变量,对其写入要和所有其他线程后续的读操作同步。因此,
使用volatile会禁止缓存,并且不做指令重排

JMM对于同步的规则定义

声明

JMM只对线程间操作生效,而对线程内无效

内容:

1.对volatile 变量V的写入,与所有其他线程后续对V的读同步
2.对于监视器m的解锁与所有后续操作对于m的加锁同步。
3.每个属性写入的默认值,与每个线程对其进行的操作同步
4.启动线程的操作和线程第一个操作同步
5.线程T2的最后操作和线程T1发现线程T2已经结束同步。
6.如果T1中断了T2那么其他线程会同步发现T2停止。通常抛出InterrruptedException。

final在jmm中的处理

1.final在该对象的狗仔函数中色湖之对象的字段,当线程看到该对象时,将始终看到该对象的final字段的正确构造。
2.如果在投在函数中设置字段后发生读取,则会看到该final字段分配的值,否则他将会看到默认值。

字节分裂处理

不要对byte[]进行重新赋值。更不要在多线程程序中这样做。存在赋值被覆盖

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值