java - 多线程:操纵同一对象的不同字段的线程

标签 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())。
我是否会遇到与多线程相关的任何典型问题?
我的问题
  • 我认为关于a和c我可能不会面临任何竞争条件,因为它们不是由“他们”线程以外的线程读取的。这个推理对吗?
  • T2和T3的x.getB()怎么样?
  • 在多核环境中如何由处理器进行缓存?他们缓存整个对象吗?还是只缓存他们修改的字段?还是他们缓存整个内容,但只更新他们更改的字段?
  • 他们甚至可以识别对象和字段吗?还是只在内存块上工作?在那种情况下,Java是否告诉他们需要缓存的内存地址?

  • 当处理器在处理完成后将其缓存与主内存进行调和时,它们是否仅更新更改的内存块,还是用其缓存的整个内存块覆盖了主内存?
    例如,最初,a和c都具有a = 1c = 1值。 P1和P4缓存这些值(a=1c=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的值。

    最佳答案

    您质疑许多有趣的话题。我将尝试重新整理您的问题,并按顺序回答。
    关于第一个问题:如果不同的线程仅修改不同的对象,这会带来一致性问题吗?
    您需要在修改对象(或“写入”)与使此类更改对其他线程可见之间做出区分。在您出现的情况下,您的各种线程彼此独立地处理各种对象,而无需“读取”其他对象。是的,这很好。
    但是,如果一个线程需要读取可能已被另一个线程修改的变量的值,则需要引入一些同步,以便在第一个线程读取之前对该变量进行修改(同步块(synchronized block)/访问 volatile 变量/信号量等)。我对这篇文章Fixing the Java Memory Model不够推荐。
    关于第二个问题:
    对第一个问题的回答相同:只要没有线程修改b实例的成员X,就无需担心;线程T2T3将获得相同的对象。
    关于第三个和第四个问题,缓存一致性如何?
    从程序员的角度来看,Java虚拟机如何处理内存分配是有点晦涩的。您所关注的被称为虚假共享。 Java虚拟机将确保存储在内存中的内容与您的程序一致。您无需担心不良的高速缓存会覆盖另一个线程所做的更改。
    但是,如果成员之间有足够的争用,您可能会面临性能下降的问题。幸运的是,您可以通过在存在问题的成员上使用 @Contended 注释来减少这种影响,这些成员会向Java虚拟机指示应在不同的缓存行上分配它们。

    关于java - 多线程:操纵同一对象的不同字段的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66380065/

    相关文章:

    c++ - 在 C++ 中终止线程的正确方法

    java - Java字符串的PGP加密

    java - 我们如何在原始类型上使用 .class?

    java - 尝试在使用 KeyListener 时插入字符

    java - 如何将 CompletableFuture 与 Spring Boot 结合使用以提供可靠的服务

    caching - proxy_cache_min_uses 时间窗口

    c# - 如何在 .NET 3.5 中从 .NET 4 功能实现 Barrier 类

    java - Java 1.4 中 Lock.tryLock() 的替代方案

    caching - Elixir 进程占用过多内存

    tomcat - mod_cache 返回 "broken expires header"