我需要一些JAVA理论的帮助...
所以我最近发现,如果一个应用程序使用多个线程,并且不同线程有可能同时访问同一个共享变量,那么应该使用" synchronized"获取/设置所述变量的方法。
所以...在我的(位置感知)应用程序中,我有变量LAT和属于MainActivity的LON并且是静态的。可以从后台服务访问它们:
appendToPOST(MainActivity.LAT);
在MainActivity本身,我使用谷歌播放位置服务,因此在MainActivity中的onLocationChanged()回调方法中,我有:
LAT = [arbitrary Double value goes here];
因此,这意味着我应该实施:
public static synchronized void setLAT(Double inLAT){
LAT = inLAT;
}
public static synchronized void setLON(Double inLON){
LON = inLON;
}
public static synchronized Double getLAT(){
return LAT;
}
public static synchronized Double getLON(){
return LON;
}
正确?感谢您的任何澄清/帮助。
补充:另外,我是否应该更改onLocationChanged()方法中的代码以使用synchronized方法,即使它与变量存在于同一个类中?
答案 0 :(得分:2)
首先,synchronized static methods
是Java内置锁的类型。它们使用类对象作为锁,因此一次只有一个线程可以使用该类。如果一个线程执行其中一个方法,则其他线程无法执行任何对象方法。这是锁定类型的同步。它会影响性能。但如果不需要高性能,此解决方案将起作用。您需要标记使用synchronized
关键字读取/更改数据的方法。
其次,我假设你的变量意味着位置的坐标:纬度和经度。如果是这样,则必须一起访问它们。您可以创建新的复合类。如果不同时访问它们,可能会导致竞争状态。
PS:如果同步影响性能,请告诉我们。在类级解决方案中存在非锁定。
答案 1 :(得分:1)
到目前为止,您的更改是正确的。正如您已经提到的那样,对这些共享状态变量的每次访问(本地访问)都必须使用同步访问器。
此外,如果LAT
和LON
的值属于一起(我假设您使用这些值表示某个位置),则应确保无法相互独立地修改或检索它们。那就是你不应该为每个值添加一个setter和getter,而是为两者添加一个。如果这些值属于一起,您可以考虑引入一个代表
public class Location {
private double mLon;
private double mLat;
// Add getters and setters. These don't need to be synchronized
}
并将MainActivity
中的同步访问者更改为
public static synchronized setLocation(final Location inLocation) {
...
}
为了完整性,使用synchronized
块可能是在共享状态对象上实现线程同步的最常见但不是最有效的解决方案。如果涉及性能,您应该查看java.util.concurrent
中的类。有关Lock
对象的简短介绍,请参阅here。
<强>更新强>:
使用代码示例更新了答案