标签: java-memory-model

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

考虑下面的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

从Java 5开始,volatile关键字具有释放/获取语义,以使副作用对其他线程可见(包括对非易失性变量的赋值!).拿这两个变量,例如:

int i;
volatile int v;
Run Code Online (Sandbox Code Playgroud)

请注意,这i是一个常规的非易失性变量.想象一下线程1执行以下语句:

i = 42;
v = 0;
Run Code Online (Sandbox Code Playgroud)

在稍后的某个时间点,线程2执行以下语句:

int some_local_variable = v;
print(i);
Run Code Online (Sandbox Code Playgroud)

根据Java存储器模型,v线程1中的写入以及线程2中的读取v确保线程2看到i在线程1中执行的写入,因此打印值42.

我的问题是:volatile在C#中是否有相同的发布/获取语义?

c# java volatile memory-model java-memory-model

6
推荐指数
2
解决办法
929
查看次数

实例化Java对象时,父类是自动创建的对象吗?

假设我创建了一个对象,并运行了父类的一个构造函数.使用此构造函数,在幕后创建父对象的新对象?

如果没有,private父类的字段存储在哪里?实际上,您可以调用父对象的任何方法(有或没有super),该对象操作调用对象不可见的私有字段.

如果有人最熟悉Java内存模型,那么非常欢迎他或她的回答!

java java-memory-model

6
推荐指数
1
解决办法
396
查看次数

发生在Java内存模型中的关系之前

关于JLS ch17 线程和锁,它说"如果一个动作发生在另一个之前,那么第一个动作在第二个之前可见并且在第二个之前被命令"; 我想知道:

(1)说"之前订购"的真正含义是什么?因为即使action_a发生在action_b之前,action_a也可以在action_b之后的某些实现中执行,对吧?

(2)如果action_a发生在action_b之前,是否意味着action_a绝不能看到action_b?或者action_a可能会看到或看不到action_b?

(3)如果action_a没有发生 - 在action_b之前,而action_b没有发生 - 在action_a之前,是否意味着action_a可能会看到或看不到action_b?

(4)之前没有任何循环发生,对吧?

任何答案将不胜感激:)

java jvm jvm-hotspot java-memory-model happens-before

6
推荐指数
2
解决办法
616
查看次数

原子比较和交换是否可以覆盖惰性写入而不会看到它?

JLS 的内存模型部分(17.4)以合理的细节描述了volatile非volatile读写的语义,以及与某些其他结构(如监视器进入和退出)的交互.

然而,这并不能完全解释的语义compareAndSwap,也不lazySet在java.util.concurrent.atomic中*类.因为compareAndSet,你有javadoc包中的blurb :

compareAndSet and all other read-and-update operations such as getAndIncrement 
have the memory effects of both reading and writing volatile variables. 
Run Code Online (Sandbox Code Playgroud)

lazySet 提供了一些更难以理解的模糊:

lazySet has the memory effects of writing (assigning) a volatile variable 
except that it permits reorderings with subsequent (but not previous)
memory actions that do not themselves impose reordering constraints with
ordinary non-volatile writes. Among other usage contexts, lazySet may …
Run Code Online (Sandbox Code Playgroud)

java concurrency java-memory-model jls

6
推荐指数
1
解决办法
153
查看次数

如何理解JSR-133 Happens-Before太弱了图6/7

在JSR-133中,有两个例子可能是状态正确同步的程序.

第一个例子如图6所示,其中:

x == y == 0
Run Code Online (Sandbox Code Playgroud)

然后,线程1通过以下方式修改状态:

r1 = x; 
if (r1 != 0) 
y = 1; 
Run Code Online (Sandbox Code Playgroud)

和线程2通过以下方式修改状态:

r2 = y;
if (r2 != 0)
x = 1;
Run Code Online (Sandbox Code Playgroud)

作者声明该程序已正确同步,但是,此程序的执行会导致r1 == r2 == 1.后一个价值怎么可能呢?

此外,图7表示初始状态:

x == y == 0
Run Code Online (Sandbox Code Playgroud)

用线程1修改:

r1 = x; 
y = r1; 
Run Code Online (Sandbox Code Playgroud)

和线程2执行:

r2 = y;
x = r2;
Run Code Online (Sandbox Code Playgroud)

怎么会导致这种情况r1 == r2 == 42?

java java-memory-model

6
推荐指数
1
解决办法
199
查看次数

oom-killer杀死了Docker中的java应用程序 - 报告的内存使用不匹配

我们有一个在Docker中运行的Java应用程序.它有时会被oom-killer杀死,即使所有JVM统计数据看起来都不错.我们有许多其他应用程序没有这样的问题.

我们的设置:

  • 容器大小限制:480MB
  • JVM堆限制:250MB
  • JVM元空间限制:100MB

JVM报告的各种内存统计信息(我们每隔10秒获取一次数据):

JVM统计信息

来自容器的日志(可能稍微不正常,因为我们使用相同的时间戳获取所有内容):

java invoked oom-killer: gfp_mask=0xd0, order=0, oom_score_adj=0
java cpuset=47cfa4d013add110d949e164c3714a148a0cd746bd53bb4bafab139bc59c1149 mems_allowed=0
CPU: 5 PID: 12963 Comm: java Tainted: G               ------------ T 3.10.0-514.2.2.el7.x86_64 #1
Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 04/14/2014
0000000000000000 0000000000000000 0000000000000046 ffffffff811842b6
ffff88010c1baf10 000000001764470e ffff88020c033cc0 ffffffff816861cc
ffff88020c033d50 ffffffff81681177 ffff880809654980 0000000000000001
Call Trace:
[<ffffffff816861cc>] dump_stack+0x19/0x1b
[<ffffffff81681177>] dump_header+0x8e/0x225
[<ffffffff8118476e>] oom_kill_process+0x24e/0x3c0
[<ffffffff810937ee>] ? has_capability_noaudit+0x1e/0x30
[<ffffffff811842b6>] ? find_lock_task_mm+0x56/0xc0
[<ffffffff811f3131>] mem_cgroup_oom_synchronize+0x551/0x580
[<ffffffff811f2580>] ? mem_cgroup_charge_common+0xc0/0xc0
[<ffffffff81184ff4>] pagefault_out_of_memory+0x14/0x90
[<ffffffff8167ef67>] mm_fault_error+0x68/0x12b
[<ffffffff81691ed5>] __do_page_fault+0x395/0x450
[<ffffffff81691fc5>] do_page_fault+0x35/0x90 …
Run Code Online (Sandbox Code Playgroud)

linux memory out-of-memory java-memory-model docker

6
推荐指数
1
解决办法
2521
查看次数

使用fork/join可以跨线程边界安全地移植非线程安全值吗?

我有一些不是线程安全的类:

class ThreadUnsafeClass {
  long i;

  long incrementAndGet() { return ++i; }
}
Run Code Online (Sandbox Code Playgroud)

(我在long这里使用了a 作为字段,但我们应该将其字段视为一些线程不安全的类型).

我现在有一个看起来像这样的课程

class Foo {
  final ThreadUnsafeClass c;

  Foo(ThreadUnsafeClass c) {
    this.c = c;
  }
}
Run Code Online (Sandbox Code Playgroud)

也就是说,线程不安全类是它的最后一个字段.现在我要这样做:

public class JavaMM {
  public static void main(String[] args) {
    final ForkJoinTask<ThreadUnsafeClass> work = ForkJoinTask.adapt(() -> {
      ThreadUnsafeClass t = new ThreadUnsafeClass();
      t.incrementAndGet();
      return new FC(t);
    });

    assert (work.fork().join().c.i == 1); 
  }
}
Run Code Online (Sandbox Code Playgroud)

也就是说,从thread T(main),我调用了一些工作T'(fork-join-pool),它创建并改变了我的不安全类的实例,然后返回包含在a中的结果Foo.请注意,我的线程不安全类的所有变异都发生在一个线程上T'.

问题1:我是否保证thread-unsafe-class实例的结束状态安全地移植到?的 …

java parallel-processing fork-join java-memory-model java-stream

6
推荐指数
1
解决办法
237
查看次数

java unsafe中getXXXVolatile与getXXX有什么区别?

我试图理解java unsafe中的两个方法:

   public native short getShortVolatile(Object var1, long var2);
Run Code Online (Sandbox Code Playgroud)

VS

   public native short getShort(Object var1, long var2);
Run Code Online (Sandbox Code Playgroud)

这有什么真正的区别?这里的挥发性真正起作用了什么?我在这里找到了API doc:http://www.docjar.com/docs/api/sun/misc/Unsafe.html#getShortVolatile( Object,%20long)

但它并没有真正解释两种功能之间的区别.

我的理解是,对于不稳定的,它只对我们写作时很重要.对我来说,我们调用putShortVolatile然后进行读取应该是有意义的,我们可以简单地调用,getShort()因为volatile写入已经保证新值已经刷新到主存储器中.

如果有任何问题,请帮我纠正.谢谢!

java bytebuffer unsafe volatile java-memory-model

6
推荐指数
1
解决办法
672
查看次数

Collection.parallelStream()是否意味着发生在之前的关系?

考虑这个(完全人为的)Java代码:

final List<Integer> s = Arrays.asList(1, 2, 3);
final int[] a = new int[1];
a[0] = 100;
s.parallelStream().forEach(i -> {
    synchronized (a) {
        a[0] += i;
    }
});
System.out.println(a[0]);
Run Code Online (Sandbox Code Playgroud)

此代码是否保证输出"106"?

似乎不存在,除非有一个先发生过的关系建立起来parallelStream(),通过它我们可以肯定地知道a[0]lambda 中的第一次访问将看到100而不是零(根据我对Java内存模型的理解).

但Collection.parallelStream()没有记录建立这种关系......

可以询问完成parallelStream()方法调用的相同问题.

所以我错过了一些东西,或者为了正确性,上述代码需要看起来像这样:

final List<Integer> s = Arrays.asList(1, 2, 3);
final int[] a = new int[1];
synchronized (a) {
    a[0] = 100;
}
s.parallelStream().forEach(i -> {
    synchronized (a) {
        a[0] += i;
    }
});
synchronized (a) …
Run Code Online (Sandbox Code Playgroud)

java java-memory-model java-stream

6
推荐指数
1
解决办法
160
查看次数