同步方法和静态变量访问 JAVA / ANDROID
Synchronized methods and static variable access JAVA / ANDROID
我需要一些 JAVA 理论方面的帮助...
所以我最近发现,如果一个应用程序使用多线程,并且有可能不同的线程同时访问同一个共享变量,那么应该使用"synchronized"方法来get/set表示变量。
所以...在我的(位置感知)应用程序中,我有变量 LAT 和 LON,它们属于 MainActivity 并且是静态的。它们是从后台服务访问的,如下所示:
appendToPOST(MainActivity.LAT);
并且在 MainActivity 本身中,我正在使用 google 播放定位服务,因此在 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;
}
对吗?感谢任何 clarification/help.
补充:另外,我是否应该更改 onLocationChanged() 方法中的代码以使用同步方法,即使它与变量存在于相同的 class 中?
到目前为止,您的更改是正确的。正如您已经提到的,对这些共享状态变量的每个 访问(以及本地访问)都必须使用同步访问器。
此外,如果 LAT
和 LON
的值属于一起(我假设您用这些值表示一个位置),您应该确保它们不能被修改或独立检索其他。也就是说,您不应为每个值添加 setter 和 getter,而应为两者添加一个。如果这些值属于一起,您可以考虑引入一个新的 class 来表示这两个值,例如
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
中的 classes。有关 Lock
对象的简短介绍,请参阅 here。
更新:
使用代码示例更新了答案
首先,synchronized static methods
是Java的内置锁类型。他们使用 class 对象作为锁,因此一次只有一个线程可以使用 class。如果一个线程执行其中一种方法,则其他线程无法执行任何对象方法。这是锁定类型的同步。它会影响性能。但如果不需要高性能,此解决方案将起作用。您需要使用 synchronized
关键字标记 read/change 数据的方法。
其次,我假设您的变量表示位置坐标:纬度和经度。如果是这样,则必须一起访问它们。您可以制作新的复合材料 class。如果不同时访问它们,可能会导致竞争条件。
PS:让我们知道同步是否会影响性能。有 class 级别的非锁定解决方案。
我需要一些 JAVA 理论方面的帮助...
所以我最近发现,如果一个应用程序使用多线程,并且有可能不同的线程同时访问同一个共享变量,那么应该使用"synchronized"方法来get/set表示变量。
所以...在我的(位置感知)应用程序中,我有变量 LAT 和 LON,它们属于 MainActivity 并且是静态的。它们是从后台服务访问的,如下所示:
appendToPOST(MainActivity.LAT);
并且在 MainActivity 本身中,我正在使用 google 播放定位服务,因此在 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;
}
对吗?感谢任何 clarification/help.
补充:另外,我是否应该更改 onLocationChanged() 方法中的代码以使用同步方法,即使它与变量存在于相同的 class 中?
到目前为止,您的更改是正确的。正如您已经提到的,对这些共享状态变量的每个 访问(以及本地访问)都必须使用同步访问器。
此外,如果 LAT
和 LON
的值属于一起(我假设您用这些值表示一个位置),您应该确保它们不能被修改或独立检索其他。也就是说,您不应为每个值添加 setter 和 getter,而应为两者添加一个。如果这些值属于一起,您可以考虑引入一个新的 class 来表示这两个值,例如
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
中的 classes。有关 Lock
对象的简短介绍,请参阅 here。
更新:
使用代码示例更新了答案
首先,synchronized static methods
是Java的内置锁类型。他们使用 class 对象作为锁,因此一次只有一个线程可以使用 class。如果一个线程执行其中一种方法,则其他线程无法执行任何对象方法。这是锁定类型的同步。它会影响性能。但如果不需要高性能,此解决方案将起作用。您需要使用 synchronized
关键字标记 read/change 数据的方法。
其次,我假设您的变量表示位置坐标:纬度和经度。如果是这样,则必须一起访问它们。您可以制作新的复合材料 class。如果不同时访问它们,可能会导致竞争条件。
PS:让我们知道同步是否会影响性能。有 class 级别的非锁定解决方案。