Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多线程:线程处理同一对象的不同字段_Java_Multithreading_Caching_Multiprocessing - Fatal编程技术网

Java 多线程:线程处理同一对象的不同字段

Java 多线程:线程处理同一对象的不同字段,java,multithreading,caching,multiprocessing,Java,Multithreading,Caching,Multiprocessing,假设我有一个有两个变量的类X class X { Integer a; Y b; Integer c; } Y班 class Y { Integer y1; String y2; } 比如说,我们有4个线程,T1、T2、T3和T4 T1操作于a,T2操作于b.y1(类似于x.getB().setY1()),T3操作于b.y2,T4操作于c 我不会在任何线程中读取任何“最深”的值(a,y1,y2,c),直到所有这些值都被执行(T2和T3将执行x.getB

假设我有一个有两个变量的类X

class X {
    Integer a;
    Y b;
    Integer c;
}
Y班

class Y {
    Integer y1;
    String y2;
}
比如说,我们有4个线程,T1、T2、T3和T4

T1操作于
a
,T2操作于
b.y1
(类似于
x.getB().setY1()
),T3操作于
b.y2
,T4操作于
c

我不会在任何线程中读取任何“最深”的值(
a,y1,y2,c
),直到所有这些值都被执行(T2和T3将执行
x.getB()

我会面临与多线程相关的任何典型问题吗

我的问题

  • 我想我可能不会面临关于a和c的任何竞争条件,因为它们不是由“它们的”线程以外的线程读取的。这个理由正确吗
  • T2和T3的
    x.getB()
  • 多核环境中的处理器缓存如何?他们是否缓存整个对象?还是只缓存修改的字段?或者他们会缓存整个内容,但只更新他们更改的字段
  • 他们甚至能识别物体和场吗?或者他们只是处理大块的内存?在这种情况下,Java会告诉他们需要缓存的内存地址吗
  • 当处理器在处理完成后将其缓存与主内存进行协调时,它们是只更新所更改的内存块,还是用缓存的整个内存块覆盖主内存

    例如,最初,a和c都有值
    a=1
    ,和
    c=1
    。P1和P4缓存这些值(
    a=1
    c=1
    )。T1将其更改为
    a=2
    ,T4将其更改为
    c=2

    现在,高速缓存C1中的值是
    a=2,c=1
    ;在C2中,
    a=1,c=2

    因此,当写回主存时,假设P1首先完成,然后更新主存。因此,现在的值是
    a=2,c=1

    现在,当P4完成时,它是否只更新
    c
    ,因为它只修改了
    c
    ?或者它只是用缓存中的值覆盖主内存,使
    a=1,c=2

    或者他们只是缓存将读取或写入的值,这意味着T1永远不会缓存
    c
    的值,T4永远不会缓存
    a
    的值

    我会面临与多线程相关的任何典型问题吗

    你只是在读书,所以,当然不是。你的问题根本不相关。Java内存模型描述了如何将对字段的更改传播到其他线程。这首先需要实际的更改

    他们是只更新更改的内存块,还是用缓存的整个内存块覆盖主内存

    只有他们改变了什么

    多核环境中的处理器缓存如何?他们是否缓存整个对象?还是只缓存修改的字段

    你的问题毫无意义。您根本无法将对象放入字段或变量中,这是不可能的。在字段/变量/参数中唯一可以粘贴的是对对象的引用。在
    String x=“foo”
    中,您没有将“foo”放在
    x
    中。“福”住在某个地方。您确保它存在于堆中,并将对它的引用分配给
    x
    。此引用相当简单,通常为64位,并且是原子的

    更新相关的线程之间可以共享的只有字段。方法不能更改(您不能修改某个实例的方法;java与python或javascript不同,您不能编写
    someRef.flibbledyboo=thingie;
    其中“flibbledyboo”是您刚刚编写的。局部变量(包括参数)不可能与其他线程共享;java在所有方面都是按值传递的,因此如果在方法内部执行,
    someOtherMethod(variable);
    ,则传递的是一个副本,这使得“如果我更改了变量,而someOtherMethod将其交给另一个线程会发生什么情况?”这一点无关紧要

    如果创建lambda或local类,您似乎可以与线程共享本地变量,但java将拒绝编译该类,除非该变量是final,或者实际上是final最后,这一点是没有意义的——它不能被改变,因此“如果一个线程更新了这个值,那么另一个线程什么时候看到更新”这个问题是不相关的

    因此:它只是关于字段的,字段只能包含基本值,或者引用。引用是简单的东西。如果你熟悉C,它们是指针,但这是一个肮脏的词,所以java称它们为references.Potayto,Potahto。同样的事情

    任何字段(无论是原语还是引用)都可以由任何线程缓存,也可以由经销商选择。他们可以随时将其“同步”回主内存。如果您的代码根据此更改执行方式,则您编写了一个难以发现的错误。请尽量不要这样做:)

    他们甚至能识别物体和场吗?或者他们只是处理大块的内存

    同样是一个非理性的问题,如前一点所述:您要寻找的是值:原语和引用。这就是JMM的意义所在(而不是“内存块”)。对象不能位于字段中。只有参考资料。引用指向一个对象,但该对象只是另一个包o'字段。一路上都是田野

    假设线程A执行:
    foo.getX().setY()
    ,线程B执行:
    foo.getX().getY()
    。假设
    foo
    从未更改,那么想必
    foo.getX()
    也从未更改。这只是一个引用,“.”是JavaESE的代表:遵循它,在那里找到bag o字段,并对这些字段进行操作。因此,两个线程都找到了同一个对象和实际的bag-o-fields。N