Java 中 .Net 的 Interlocked 类的等价物是什么?

发布于 2024-07-27 12:05:08 字数 61 浏览 12 评论 0原文

如何在 Java 中原子地且线程安全地修改 int?

原子增量、测试和 设置等...?

How do I modify an int atomically and thread-safely in Java?

Atomically increment, test & set, etc...?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

素衣风尘叹 2024-08-03 12:05:08

线程安全可以通过同步函数来实现。
将您的 int (或此类数据)包装在一个类中,该类通过同步方法提供所需的功能,例如

public class X
{
  protected int x;
  public synchronized void set( int value )
  {
    x = value;
  }
}

您还可以使用 java.util.concurrent.atomic 包,例如 AtomicInteger 或 AtomicIntegerArray

为什么这个答案不起作用

我只是想要确保指出这个答案到底有什么问题,以防有人认为 synchronized 可用于解决线程竞争效应。

| Thread A      | Thread B         | 
|---------------|------------------|
| read x (x=4)  |                  |
|               | read x (x=4)     |
| Calculate 4+1 |                  |
| EAX ← 5       |                  |
|               | Calculate 4+1    |
|               | EAX ← 5          |
| Start sync    |                  |
| {             | Start sync       |
| { x ← 5       |    wait          |
| {             |    wait          |
| End sync      |    wait          |
|               | {                | 
|               | { x ← 5          |
|               | {                | 
|               | End sync         |

操作的最终结果

x = 4;
x += 1;
x += 1;

是:x = 5 而不是 6。

volatile 关键字也存在同样的问题。 volatile 关键字并不能避免线程效应。 易失性关键字仅确保

  • 在读取变量之前刷新缓存,
  • 在写入值后刷新缓存。

严格来说,易失性确保内存操作不会围绕易失性变量重新排序。 这意味着您仍然遭受:

  • 从 x 读取
  • 写入 x 的

问题。

Thread safety can be achieved via synchronized functions.
Wrap your int (or such data) in a class which provides the required functionalities via synchronized methods, e.g.

public class X
{
  protected int x;
  public synchronized void set( int value )
  {
    x = value;
  }
}

You can also use classes from the java.util.concurrent.atomic package, e.g. AtomicInteger or AtomicIntegerArray

Why this answer won't work

I just wanted to be sure to point out exactly what is wrong with this answer, in case anyone thinks that synchronized can be used to solve thread race effects.

| Thread A      | Thread B         | 
|---------------|------------------|
| read x (x=4)  |                  |
|               | read x (x=4)     |
| Calculate 4+1 |                  |
| EAX ← 5       |                  |
|               | Calculate 4+1    |
|               | EAX ← 5          |
| Start sync    |                  |
| {             | Start sync       |
| { x ← 5       |    wait          |
| {             |    wait          |
| End sync      |    wait          |
|               | {                | 
|               | { x ← 5          |
|               | {                | 
|               | End sync         |

The end result of the operations:

x = 4;
x += 1;
x += 1;

is that x = 5 rather than 6.

The same issue exists with the volatile keyword. The volatile keyword doesn't save you from thread effects. The volatile keyword only ensures that

  • caches are flushed before a variable is read
  • caches are flushed after a value is written

Strictly speaking, volatile ensures that memory operations are not reordered around a volatile variable. Which means you still suffer from the:

  • read from x
  • write to x

problem.

猫烠⑼条掵仅有一顆心 2024-08-03 12:05:08
private final static AtomicInteger at = new AtomicInteger();

public void run() {
    at.set(7);
    int i = at.incrementAndGet();
private final static AtomicInteger at = new AtomicInteger();

public void run() {
    at.set(7);
    int i = at.incrementAndGet();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文