由于我对Java还是很陌生,因此我目前正在尝试多线程。现在,我有多个线程都影响同一个long变量。但是,似乎一段时间后除了检查if语句外,什么都不做,而while循环只是停止执行(例如,它无限循环)。如果我只是在while循环中打印某些内容,它确实可以工作。
不起作用:
while(true){
if(longVariable < 2)
break;
}
以某种方式起作用:
while(true){
System.out.println("hi");
if(longVariable < 2)
break;
}
这是为什么?
答案 0 :(得分:2)
while(true){
if(longVariable < 2)
break;
}
在此代码中,JVM没有理由相信longVariable
会发生变化。它可以有效地将其重写为:
long cached = longVariable;
while(true){
if(cached < 2)
break;
}
longVariable
执行时,如果cached
至少为2,则无限循环,因为System.out.println
不会改变。
您必须向编译器提示不允许进行此重写。它可以与JVM上的longVariable
一起使用,因为它恰好是通过同步实现的(这是常见的,但不是必需的)。这会插入内存屏障,这意味着volatile long longVariable
的缓存值无效,必须重新读取。
但是不能保证它能正常工作。为了使其正常工作,请声明变量volatile:
AtomicLong
这可以防止其值被缓存。
或者使用类似long
之类的东西代替普通的long v;
synchronized (something) {
v = longVariable;
}
if (v < 2) ...
变量。
或者,最麻烦的是,使用显式同步(确保对变量的所有读取和写入都在同一“事物”上同步):
import React, { Component } from 'react';
import { Text, View, TextInput, StyleSheet } from 'react-native';
import { Constants } from 'expo';
import { Tile } from 'react-native-elements';
export default class Tel extends Component {
render() {
return (
<View style={styles.tileStyle}>
<View style={{width: 20, height: 20,}}>
<Tile
featured
caption="Text"
/>
</View>
<View style={{width: 20, height: 20,}}>
<Tile
featured
caption="Some Caption Text"
/>
</View>
<View style={{width: 20, height: 20,}}>
<Tile
featured
caption="Some"
/>
</View>
<View style={{width: 20, height: 20,}}>
<Tile
featured
caption="Text"
/>
</View>
<View style={{width: 20, height: 20,}}>
<Tile
featured
caption="Some Caption Text"
/>
</View>
<View style={{width: 20, height: 20,}}>
<Tile
featured
caption="Some"
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
tileStyle: {
flex: 1,
flexDirection: 'row',
// alignItems: 'center',
// justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
}
});
答案 1 :(得分:0)
当您拥有一个不由线程更新的非易失性变量时,可以自由地内联该变量。
在第一种情况下,JIT编译代码后,它可能不再读取该值,而是使条件始终为真。
在第二种情况下,您具有线程安全操作。 println
上的System.out
是一种synchronized
方法。这样会增加读写障碍,并阻止JIT优化读取操作。
如果您尝试这样做,它也应该起作用。
while(true){
synchronized("hi") { } // does nothing but add memory barriers.
if(longVariable < 2)
break;
}
这还会使代码减慢1000倍以上,因此在您尝试停止线程时,该方法可能尚未JIT。
简单的解决方案是使变量volatile
每次都将以线程安全的方式读取。