gpt4 book ai didi

java - 跨多个线程访问字符串

转载 作者:搜寻专家 更新时间:2023-11-01 01:26:12 24 4
gpt4 key购买 nike

我在这里寻找一些输入。我有一个单例类,其中包含一个值,该值每隔几秒由该类中的一个方法更新一次。现在,跨多个线程访问这个值是通过同步完成的,我想消除它。这有意义吗?

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;
}
}
}

可以有很多 DataSegment 实例都从 myValue 读取,但是度量类是单例。 myValue 仅每 5 秒左右更新一次,并且只允许 MetricsUpdater 写入它。这有意义吗?

如果只允许所有其他线程读取它,它甚至还需要同步吗?我对此运行了大量 JUnit 测试,创建了许多 DataSegment 类的实例,所有这些都疯狂地打印值,我还没有看到任何并发问题。

最佳答案

您的代码存在一些问题。

第一个问题

synchronized(myValue) {
myValueSynchronized = someMethodToUpdateMyValue();
myValue = myValueSynchronized;
Thread.sleep(100);
}

您的关键部分是错误的,因为正在锁定 myValue。假设您在退出临界区之前放置了一个 Thread.sleep(100)。然后这意味着其他线程将锁定新的 myValue 实例,从而可以进入临界区。如果它是一个时间线程并且它的频率非常高。然后你可以让陈旧的更新覆盖新的。无论如何,获取此类监视器的锁定是一种不好的做法。在 String 的某些最终引用上使用 ReentrantLock 或同步。

第二题

    public static MetricsUpdater getInstance() {
if (theInstance == null) {
theInstance = new MetricsUpdater();
}
return theInstance;
}

您的单例代码已损坏。使用 DCL(双重检查锁定,请参阅下面我的解决方案部分)。或者使用 private static MetricsUpdater theInstance = new MetricsUpdate();。后者更好,

第三题

 sb.append(metrics.myValue); 

以上代码应在同步上下文中调用或声明为易变的。后者更好

解决方案 1 - 假设 someMethodToUpdateMyValue 是线程安全的

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();
}
}

解决方案 2:假设 someMethodToUpdateMyValue 不是线程安全的

不需要同步是引用读/写是原子的并且我们已将 myValue 声明为 volatile

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();
}
}

}

关于java - 跨多个线程访问字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24831636/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com