标签: java-memory-model

Conway生命游戏的多线程Java程序 - 边界单元的争用

我正在学习java中的并发编程,并为Game of Life编写模拟.

这就是我的想法:

  • 使用int [] []存储单元格的状态
  • 将int [] []分区为t段并使用t个工作线程
  • t个线程将从其段读取,计算其段中所有单元的新值并更新单元.
  • 一旦他们完成计算,他们就会等待其他工人的障碍完成
  • 当屏障被越过时,主线程将更新UI.
  • 工人们继续计算下一个州.

现在,这些细分市场的共同边界将会发生争执.如果一个线程在其邻居读取了之前的值之前覆盖了边界单元的状态,则该邻居的计算将是错误的.

我有什么选择?

  • 使用callable而不是runnable并让工作线程返回新值(而不是更新段本身).穿过屏障后,主线程可以更新矩阵.此选项涉及将工作线程返回的结果复制到矩阵中.
  • 使用两个障碍.工作者线程从邻居的段中复制边界单元格并在第一道屏障处等待.一旦通过此障碍,他们就会继续计算下一个状态并更新到位.然后他们在第二道屏障等候.主线程更新UI.

我的问题是,有没有其他方法可以处理边界单元中不涉及复制数据的争用,还是更有效的上述两种选择?可能是使用ReaderWriterLock,volatile变量还是其他同步机制?

更新:到目前为止,彼得的双缓冲解决方案是最干净的解决方案.但我有一个问题.由于这两个数组是共享数据而我们没有使用任何同步(同步访问或volatile变量),它是否会产生可见性问题?多个CPU可以缓存数组值并在每次迭代时只更新数组的一部分吗?然后线程将获得边界单元格的陈旧值.这可能吗?如果没有,为什么.如果是,我该如何解决?似乎声明两个数组volatile不会使它们各自的元素变得易变.

java multithreading synchronization java-memory-model conways-game-of-life

8
推荐指数
2
解决办法
3683
查看次数

具有非final字段的不可变对象如何是线程不安全的?

说我们有这个

// This is trivially immutable.
public class Foo {
    private String bar;
    public Foo(String bar) {
        this.bar = bar;
    }
    public String getBar() {
        return bar;
    }
}
Run Code Online (Sandbox Code Playgroud)

是什么让这个线程不安全?继这个问题之后.

java concurrency multithreading java-memory-model

8
推荐指数
3
解决办法
1018
查看次数

如何使用volatile变量编写一个简单的线程安全类?

我想编写一个简单的线程安全类,可用于设置或获取Integer值.

最简单的方法是使用synchronized关键字:

public class MyIntegerHolder {

    private Integer value;

    synchronized public Integer getValue() {
        return value;
    }

    synchronized public void setValue(Integer value) {
        this.value = value;
    }

}
Run Code Online (Sandbox Code Playgroud)

我也可以尝试使用volatile:

public class MyIntegerHolder {

    private volatile Integer value;

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

}
Run Code Online (Sandbox Code Playgroud)

具有volatile关键字的类是否是线程安全的?

考虑以下事件序列:

  1. 线程A将值设置为5.
  2. 线程B将值设置为7.
  3. 线程C读取值.

它遵循Java语言规范

  • "1" 发生在 "3" 之前
  • "2" 发生在 "3" 之前

但我不知道它是如何遵循规范"1" 发生 …

java concurrency multithreading java-memory-model

8
推荐指数
1
解决办法
4011
查看次数

Java Memory Model: a JLS statement about sequential consistency seems incorrect

I'm reading Chapter 17. Threads and Locks of JLS and the following statement about sequential consistency in Java seems incorrect to me:

If a program has no data races, then all executions of the program will appear to be sequentially consistent.

They define a data race as:

When a program contains two conflicting accesses (§17.4.1) that are not ordered by a happens-before relationship, it is said to contain a data race.

They define conflicted accesses as:

Two accesses to (reads …

java java-memory-model jls

8
推荐指数
1
解决办法
202
查看次数

线程是否可以先通过安全发布获取对象,然后不安全地发布它?

阅读此答案后,我想到了这个问题。

代码示例:

class Obj1 {
  int f1 = 0;
}

volatile Obj1 v1;
Obj1 v2;

Thread 1            | Thread 2 | Thread 3
-------------------------------------------------
var o = new Obj1(); |          |
o.f1 = 1;           |          |
v1 = o;             |          |
                    | v2 = v1; |
                    |          | var r1 = v2.f1;

Is (r1 == 0) possible?
Run Code Online (Sandbox Code Playgroud)

这里的对象o:

  • 首次安全发布:从Thread 1到Thread 2通过volatile字段v1
  • 然后不安全地发布:从Thread 2到Thread 3 …

java multithreading java-memory-model jls safe-publication

8
推荐指数
2
解决办法
373
查看次数

最终的多线程保证和Java中的内存模型有什么关系?

内存模型在 17.4 中定义。内存模型。

17.5 中给出了现场final多线程保证。最终字段语义。

我不明白为什么这些是单独的部分。

AFAIKfinal和内存模型都提供了一些保证。
任何真正的程序执行都必须遵守这两个保证。
但现在很清楚这些final保证是否适用于用于验证 17.4.8 中因果关系要求的中间执行。执行和因果关系要求。

另一个不清楚的时刻是17.5.1。Final Fields 的语义定义了一个新的“special” ,它与内存模型happens-before中的不同:happens-before

此happens-before排序不会与其他happens-before排序传递地关闭。

如果它们相同happens-before,则happens-before不再是偏序(因为它不具有传递性)。
我不明白这怎么不会破坏事情。

如果这些不同happens-before,那么就不清楚 17.5 中的是什么。Final Field Semantics确实如此。17.4中
的。内存模型用于限制读取可以返回的内容:happens-before

非正式地,如果没有happens-before排序来阻止r读取,则允许读取查看写入的结果。w

但是17.5。最后的字段语义是一个不同的部分。

java final java-memory-model jls happens-before

8
推荐指数
1
解决办法
181
查看次数

传递应用程序活动方法的命令模式?

在阅读了@RomainGuy 的避免内存泄漏文章后,我意识到我当前的Android应用程序一直困扰着传递应用程序主要活动的错误.所以每当我,我可以简单地用Activity.getApplicationContext()替换该活动参数.

但是我的应用程序中的某些类仍然需要运行只能是应用程序主要活动成员的方法.

因此我想到可能使用命令模式来解决这个限制.

问题是,如果我们看一下这个例子:

public class SomeCommandExecuableOnlyByActivity implements Command 
{
    public void execute(Object data) 
    {
        doIt( ((MyActivity)data).getWindow() );
    }    
}
Run Code Online (Sandbox Code Playgroud)

我再次进入需要传递活动的死胡同(这次伪装成Object数据).

如何摆脱这种"鸡蛋和鸡蛋"的局面?

有没有更好的方法来解决这个问题?

android memory-leaks command-pattern java-memory-model android-activity

7
推荐指数
1
解决办法
2140
查看次数

是否保证在另一个线程中看到一个线程中的非易失性成员变量的赋值?

考虑下面的Java示例.请注意,两个类成员变量都没有声明为volatile.如果我正在理解内存模型并且"之前发生"规则正确,那么Java实现可以优化该run()方法,以便它永远运行,即使另一个线程调用该stopNow()方法.这可能发生,因为run()方法中没有任何内容强制线程stop多次读取值.那是对的吗?如果没有,为什么不呢?

class Example implements Runnable {
    boolean stop = false;
    int value = 0;

    public void stopNow() {
       stop = true;
    }

    public int getValue() {
        return value;
    }

    @Override
    public void run() {
        // Loop until stop is set to true.
        while (!stop) {
            ++value;
        }
        return;
    }
}
Run Code Online (Sandbox Code Playgroud)

java multithreading java-memory-model

7
推荐指数
1
解决办法
552
查看次数

volatile + immutable holder object =线程安全吗?

我从"java concurrency pratique"一书中得到了一个例子,他说易失性和不可变的持有者对象给出了线程安全性.但我不明白这本书给出的例子.

代码如下:

public class VolatileCachedFactorizer extends GenericServlet implements Servlet {

  private volatile OneValueCache cache = new OneValueCache(null, null);

  public void service(ServletRequest req, ServletResponse resp) {
    BigInteger i = extractFromRequest(req);
    BigInteger[] factors = cache.getFactors(i);
    if (factors == null) {             
        factors = factor(i);  //----------> thread A
        cache = new OneValueCache(i, factors);  //---------> thread B
    }
    encodeIntoResponse(resp, factors);
  }   
 }

public class OneValueCache {

  private final BigInteger lastNum;
  private final BigInteger[] lastFactors;

  public OneValueCache(BigInteger i, BigInteger[] lastFactors){
    this.lastNum = i;
    this.lastFactors …
Run Code Online (Sandbox Code Playgroud)

java volatile immutability thread-safety java-memory-model

7
推荐指数
1
解决办法
746
查看次数

Java中的synchronized构造是否在内部(以某种方式)使用硬件原语CAS操作?

我有一个很难理解什么是硬件支持的synchronized声明和相关的notify(),notifyAll()和wait()方法,目前所有的Java对象.

我已阅读并知道如何使用此构造,但我一直认为它们直接映射到硬件基元.

当我进一步深入研究有关并发性的书籍时,我只阅读了由硬件直接提供的比较和交换(CAS)操作.

似乎这些构造是由JVM本身创建/维护的.如果我的读数正确,则每个对象都包含一些状态,其中包含有关访问它的线程的信息.这用于定义该对象的监视器并协调多个线程对该对象的访问.
但如果是这种情况,这个状态本身如何通过并发访问来管理?它一定要管理,对吗?是CAS吗?

如果是CAS,那意味着只有一种真正的同步形式CAS.所有其他都是衍生品.那么,为什么是这台显示器构建与关联synchronized,notify(),notifyAll(),wait()开发给出的方法是,原子变量(即CAS)是在性能方面更好,也无等待?

我知道用户类的原子变量只出现在Java 5.0之后,但在此之前,Java已经监视/内部锁.他们是如何实施的?

java concurrency synchronization scala java-memory-model

7
推荐指数
1
解决办法
119
查看次数