AWT*_*AWT 5 java multithreading synchronization
我正在这里寻找一些意见。我有一个单例类,其中包含一个值,该值由该类中的方法每隔几秒更新一次。现在,跨多个线程访问该值是通过同步完成的,我想消除同步。这有意义吗?
class DataSegment {
private MetricsUpdater metrics = new MetricsUpdater.getInstance();
public String printValues() {
StringBuilder sb = new StringBuilder();
sb.append(value1);
sb.append(morevalues);
sb.append(metrics.myValue); // this is the value that's currently synchronized
return sb.toString();
}
}
class MetricsUpdater {
private String myValueSynchronized;
public String myValue;
public static MetricsUpdater getInstance() {
if (theInstance == null) {
theInstance = new MetricsUpdater();
}
return theInstance;
}
// this runs on a timer but to keep it simple I'll just define the method...
private void updateMetrics() {
synchronized(myValue) {
// also, to keep things simple, I've replaced all of the actual logic with a method called someMethodToUpdateMyValue()
myValueSynchronized = someMethodToUpdateMyValue();
myValue = myValueSynchronized;
}
}
}
Run Code Online (Sandbox Code Playgroud)
可以有许多 DataSegment 实例都从 myValue 读取,但指标类是单例。myValue 仅每 5 秒左右更新一次,并且仅允许 MetricsUpdater 对其进行写入。那有意义吗?
如果只允许所有其他线程读取它,它是否还需要同步?我对此运行了大量 JUnit 测试,创建了 DataSegment 类的许多实例,所有打印值都像疯狂一样,而且我还没有看到任何并发问题。
您的代码存在一些问题。
synchronized(myValue) {
myValueSynchronized = someMethodToUpdateMyValue();
myValue = myValueSynchronized;
Thread.sleep(100);
}
Run Code Online (Sandbox Code Playgroud)
您的关键部分是错误的,因为正在锁定 myValue。假设您在退出临界区之前放置了 Thread.sleep(100) 。那么这意味着其他线程将锁定新的 myValue 实例,从而可以进入临界区。如果它是一个时间线程并且它的频率是否非常高。然后你可以用旧的更新覆盖新的。无论如何,在此类监视器上获取锁定是一种不好的做法。使用 ReentrantLock 或同步 String 的某些最终引用。
public static MetricsUpdater getInstance() {
if (theInstance == null) {
theInstance = new MetricsUpdater();
}
return theInstance;
}
Run Code Online (Sandbox Code Playgroud)
您的单例代码已损坏。使用 DCL(双重检查锁定,请参阅下面我的解决方案秒)。或者使用 private static MetricsUpdater theInstance = new MetricsUpdate();。后者比较好,
sb.append(metrics.myValue);
Run Code Online (Sandbox Code Playgroud)
上面的代码应该在同步上下文中调用或声明为易失性。后者更好
class MetricsUpdater {
private static volatile MetricsUpdater theInstance;
public volatile String myValue;
/**
* DCL . Please avoid
* Better use
* private static MetricsUpdater theInstance = new MetricsUpdate();
*/
public static MetricsUpdater getInstance() {
if (theInstance == null) {
synchronized(MetricsUpdate.class) {
if(theInstance == null) {
theInstance = new MetricsUpdater();
}
}
}
return theInstance;
}
// this runs on a timer but to keep it simple I'll just define the method...
// if your someMethodToUpdateMyValue is thread safe
private void updateMetrics() {
myValue = someMethodToUpdateMyValue();
}
}
Run Code Online (Sandbox Code Playgroud)
不需要同步,引用读/写是原子的,并且我们已将 myValue 声明为易失性
class MetricsUpdater {
private static volatile MetricsUpdater theInstance;
public volatile String myValue;
/**
** Use ReentrantLock instead
*/
private final Object lock = new Object();
/**
* DCL . Please avoid
* Better use
* private static MetricsUpdater theInstance = new MetricsUpdate();
*/
public static MetricsUpdater getInstance() {
if (theInstance == null) {
synchronized(MetricsUpdate.class) {
if(theInstance == null) {
theInstance = new MetricsUpdater();
}
}
}
return theInstance;
}
// this runs on a timer but to keep it simple I'll just define the method...
private void updateMetrics() {
synchronized(lock) {
myValue = someMethodToUpdateMyValue();
}
}
Run Code Online (Sandbox Code Playgroud)
}
| 归档时间: |
|
| 查看次数: |
3868 次 |
| 最近记录: |