我正在学习java中的并发编程,并为Game of Life编写模拟.
这就是我的想法:
现在,这些细分市场的共同边界将会发生争执.如果一个线程在其邻居读取了之前的值之前覆盖了边界单元的状态,则该邻居的计算将是错误的.
我有什么选择?
我的问题是,有没有其他方法可以处理边界单元中不涉及复制数据的争用,还是更有效的上述两种选择?可能是使用ReaderWriterLock,volatile变量还是其他同步机制?
更新:到目前为止,彼得的双缓冲解决方案是最干净的解决方案.但我有一个问题.由于这两个数组是共享数据而我们没有使用任何同步(同步访问或volatile变量),它是否会产生可见性问题?多个CPU可以缓存数组值并在每次迭代时只更新数组的一部分吗?然后线程将获得边界单元格的陈旧值.这可能吗?如果没有,为什么.如果是,我该如何解决?似乎声明两个数组volatile不会使它们各自的元素变得易变.
java multithreading synchronization java-memory-model conways-game-of-life
说我们有这个
// 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)
是什么让这个线程不安全?继这个问题之后.
我想编写一个简单的线程安全类,可用于设置或获取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关键字的类是否是线程安全的?
考虑以下事件序列:
它遵循Java语言规范
但我不知道它是如何遵循规范"1" 发生 …
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 …
代码示例:
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字段v1Thread 2到Thread 3 …内存模型在 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。最后的字段语义是一个不同的部分。
在阅读了@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
考虑下面的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 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) 我有一个很难理解什么是硬件支持的synchronized声明和相关的notify(),notifyAll()和wait()方法,目前所有的Java对象.
我已阅读并知道如何使用此构造,但我一直认为它们直接映射到硬件基元.
当我进一步深入研究有关并发性的书籍时,我只阅读了由硬件直接提供的比较和交换(CAS)操作.
似乎这些构造是由JVM本身创建/维护的.如果我的读数正确,则每个对象都包含一些状态,其中包含有关访问它的线程的信息.这用于定义该对象的监视器并协调多个线程对该对象的访问.
但如果是这种情况,这个状态本身如何通过并发访问来管理?它一定要管理,对吗?是CAS吗?
如果是CAS,那意味着只有一种真正的同步形式CAS.所有其他都是衍生品.那么,为什么是这台显示器构建与关联synchronized,notify(),notifyAll(),wait()开发给出的方法是,原子变量(即CAS)是在性能方面更好,也无等待?
我知道用户类的原子变量只出现在Java 5.0之后,但在此之前,Java已经监视/内部锁.他们是如何实施的?
java ×9
concurrency ×3
jls ×3
android ×1
final ×1
immutability ×1
memory-leaks ×1
scala ×1
volatile ×1