RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 803209
Accepted
selya
selya
Asked:2020-03-23 00:38:33 +0000 UTC2020-03-23 00:38:33 +0000 UTC 2020-03-23 00:38:33 +0000 UTC

关于多线程的几个问题

  • 772

我自己已经用 java 写了很多年了,但只是作为一种爱好,我不必经常使用多线程。

有几个问题很有趣,即:

  1. 假设我需要在某个对象(来自不同线程)上编写和读取原始类型。假设这些字段是打开的 ( public)。

    根据java帮助,读写引用的操作是原子的(逻辑上,因为这种引用的大小通常放在一个处理器寄存器中,系统支持)。然后读取和写入存储对对象的引用的字段是在不同线程中执行的完全正常的操作。

    此外,java 帮助确保读取和写入基本类型(不包括longand double)也是原子的。但是这两个呢?据我了解,它们只需要标记为volatile. 但是是否有任何副作用,或者这个修饰符只是保证了对变量的操作的原子性?

    好的。现在,例如,我想通过 getters-setter 读取和写入字段。如果我的 getter-setter 不改变任何外部数据的状态,而只是读取和写入一个变量,我是否足以将这样的变量标记为volatile,或者我应该将 getter/setter 标记为syncronized?(前提是只能通过 getter 和 setter 访问变量)。

  2. 处理对象。具体来说,对于不改变状态的对象。

    例如,String。据我所知,这种类型永远不会改变 state,它所有返回字符串的方法都会返回一个新实例。

    那么,我可以在没有额外同步的情况下从不同的线程访问这样的对象吗?或者我可能会错过一些东西(当我只能获取对象但不能更改引用它的字段的值时的问题)。

感谢可以回答这些问题的人的耐心)

java
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Nofate
    2020-03-23T00:45:51Z2020-03-23T00:45:51Z
    1. 重要的是它volatile保证了可见性。一个线程中对 volatile 字段的更改将立即在另一个线程中可见。如果您需要线程安全地执行比赋值更复杂的过程,请使用同步或j.u.c.Atomic*-types 来避免竞争条件。

      示例:任何多线程计数器

      // Плохо 
      private volatile long counter;
      
      public long getId() { 
          counter += 1;
          return counter;
      }
      
      // Хорошо
      private volatile AtomicLong counter = new AtomicLong(0);
      
      public long getId() { 
          return counter.incrementAndGet();
      }
      
      // Тоже хорошо
      private volatile long counter;
      
      public synchronized long getId() { 
          counter += 1;
          return counter;
      }
      

      请记住synchronized- 这始终是一个显式锁定(但它非常便宜且竞争低),并且 Atomic 原语使用带有 CAS 指令的无限循环并且可以很好地优化。


    1. 具有不可变状态的对象(例如,此类对象的所有字段final)称为不可变对象,可以安全地在不同线程中使用它们。但是,如果对象的内部状态包含某种可变组件并且可以通过某种方式从外部访问,则您将不得不另外考虑线程安全。例子:

      // потокобезопасный класс 
      public final class SafeFoo { 
          private final Date date = new Date();
      }
      
      
      // не потокобезопасный класс 
      public final class UnsafeFoo { 
          private final Date date = new Date();
          public Date getDate() { return date; }
      }
      

      第一个类是完全线程安全的。第二个 - 没有。该方法getDate()将内部状态发布到外部代码(不安全发布)。在外面的某个地方,你可以通过改变内部状态来做到这一点:

      unsafeFoo.getDate().setHours(0);
      

      您可以保护自己免受这种情况的影响,例如,通过创建副本:

      // потокобезопасный класс 
      public final class SafeAgainFoo { 
          private final Date date = new Date();
          public Date getDate() { return date.clone(); }
      }
      
    • 4

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5