相关疑难解决方法(0)

Java VM上的内存障碍和编码风格

假设我有一个静态复杂对象,它由一个线程池定期更新,并在一个长时间运行的线程中或多或少地连续读取.对象本身总是不可变的,反映了最近的某种状态.

class Foo() { int a, b; }
static Foo theFoo;
void updateFoo(int newA, int newB) {
  f = new Foo();
  f.a = newA;
  f.b = newB;
  // HERE
  theFoo = f;
}
void readFoo() {
  Foo f = theFoo;
  // use f...
}
Run Code Online (Sandbox Code Playgroud)

我至少不在乎我的读者是看到旧的还是新的Foo,但是我需要看到一个完全初始化的对象.IIUC,Java规范说没有HERE中的内存屏障,我可能会看到一个fb初始化但尚未提交到内存的对象.我的程序是一个真实世界的程序,它迟早会将内容提交到内存中,所以我不需要立即将新的值ofFoo提交到内存中(虽然它不会受到伤害).

您认为实现内存屏障最可读的方式是什么?如果需要,我愿意为了可读性而付出一点性能价格.我想我可以将赋值同步到Foo,这样可行,但是我不确定读取代码的人为什么这么做是非常明显的.我还可以同步新Foo的整个初始化,但这会引入更多实际需要的锁定.

你会如何编写它以使其尽可能可读?
对Scala版本的奖励荣誉:)

java concurrency scala

26
推荐指数
1
解决办法
6566
查看次数

这个单例模式线程安全吗?

我有一个单例服务器实例,我很好奇我的代码是否是线程安全的.我已经阅读了不同的单例模式,我认为通常的方法是double-checked locking模式,如下所示:

public static Singleton getInstance() {
    if(singleton == null) {
        synchronized(Singleton.class) {
            if(singleton == null) {
                singleton = new Singleton();
            }
        }
    }
    return singleton;
}
Run Code Online (Sandbox Code Playgroud)

这被认为是设置/获取单身的有效线程安全方式.我读过,获取和设置单例的最简单方法是lazy instantiation,看起来像这样:

public static ClassicSingleton getInstance() {
    if(instance == null) {
        instance = new ClassicSingleton();
     }
     return instance;
}
Run Code Online (Sandbox Code Playgroud)

现在我想知道的是我的变体是否是线程安全的.我的代码:

public static void startServer(int listeningPortNumber) throws IOException {
    if (server != null) {
        throw new IOException("Connection exists");
    }

    server = new Server(listeningPortNumber);
}
Run Code Online (Sandbox Code Playgroud)

我的代码与上面的惰性实例化模式非常相似,但我看不出我的代码是如何不是线程安全的.有没有我没看到的东西,或者这是真正有效的代码?


参考: …

java singleton thread-safety

4
推荐指数
1
解决办法
3545
查看次数

是一个只更新Scala中单个var线程安全的类实例吗?

我需要在多线程环境中在Scala中缓存一些东西.

阅读scalaz,Memo我在不可变哈希映射备忘录的代码中找到了以下注释:

由于此备忘录使用单个var,因此它是线程安全的.

代码如下所示:

  def immutableMapMemo[K, V](m: Map[K, V]): Memo[K, V] = {
    var a = m

    memo[K, V](f =>
      k => {
        a get k getOrElse {
          val v = f(k)
          a = a updated (k, v)
          v
        }
      })
  }
Run Code Online (Sandbox Code Playgroud)

说这是线程安全的,与我到目前为止所阅读和学到的关于JVM平台上的线程安全的内容相反; 参考更新可能是原子的,但正如我所理解的那样,如果您没有内存屏障,编译器可能会尝试进行某些优化来扰乱发生在之前的关系.例如,请参阅此帖此内容.

但我确信那些scalaz人非常聪明.也许有关于范围的特别之处a.

评论声称是真的,如果是,为什么?

scala hashmap memoization thread-safety scalaz

2
推荐指数
1
解决办法
145
查看次数