RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1288290
Accepted
unkn0wn
unkn0wn
Asked:2022-05-31 21:15:40 +0000 UTC2022-05-31 21:15:40 +0000 UTC 2022-05-31 21:15:40 +0000 UTC

如何解决 Java 多线程中同步方法的问题?

  • 772

为了可靠性,我将引用 Bruce Eckel 的书 - Java 哲学(第 4 版)中的引述。

我们任务的逻辑很简单:
有一个类有一个i将递增的变量和一个方法,该方法反过来会增加变量的值i。

创建类布局:

public class AtomicityTest {
    private int i = 0;

    public int getValue() {
        return this.i;
    }

    public void evenIncrement() {
        i++;
        i++;
    }
}

我们有一个变量i,将来会被多个线程访问。关于这个主题,布鲁斯·埃克尔写道:

如果多个任务同时访问一个字段,则应使用 volatile 关键字声明该字段。

好的,现在我们的类字段应该如下所示:

private volatile int i = 0;

但他在下面写道:

在 Java 虚拟机инкремент 中不是原子的......

在示例中,我们将在方法中使用атомарную自增操作++。Атомарная операция- 这是:

线程调度程序无法中断的操作 - 如果它启动,它会一直持续到完成,没有上下文切换的可能性。

我们最终会得到什么?事实证明,该操作++不是原子的,因此,声明它没有意义volatile,对吧?

阅读更多

要控制对共享资源的访问,首先将其放在对象中。之后,任何访问资源的方法都可以声明为synchronized. 这意味着如果一个任务在一个声明为同步的方法中运行,所有其他任务将无法访问它们的synchronized方法,直到第一个任务从其调用中返回。

结果,我们完成了一个类:

public class AtomicityTest implements Runnable {
    private int i = 0;

    public int getValue() {
        return this.i;
    }

    public synchronized void evenIncrement() {
        i++;
        i++;
    }

    @Override
    public void run() {
        while (true) {
            evenIncrement();
        }
    }
}

由于变量的初始值为i,0并且该方法evenIncrement()将 byединице与变量相加,因此我们最终只能得到偶数。既然方法是同步的,那么:

  • 线程#1 将进入方法;
  • 将阻止其他线程对该方法的访问;
  • 将使变量增加2(0、2、4、6、8等)
  • 线程#1 将退出并解锁其他线程对该方法的访问。

好的,现在让我们开始测试:

AtomicityTest at = new AtomicityTest();

        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(at);

        while (true) {
            int value = at.getValue();

            if(value % 2 != 0) {
                System.out.println("value: " + value);
                System.exit(0);
            }
        }

然后奇迹。事实证明,在测试时,我们在输出端得到奇数。这怎么可能?问题的解决方案在于,返回一个i带有名称的值的方法getValue()应该像这样声明:

public synchronized int getValue() {
    ...
}

但为什么就这样呢?毕竟,一切都由上面的报价确认,并且应该在逻辑上工作,没有同步方法getValue()。

java
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Regent
    2022-05-31T22:34:24Z2022-05-31T22:34:24Z

    volatile例如,在这个问题中对其进行了更详细的描述。简而言之,volatile这主要是关于线程之间值的可见性,而不是关于原子性

    在报价中

    在第一个任务从其调用返回控制权之前,所有其他任务将无法进入它们的同步方法

    表示如果调用了一个方法,则synchronized不能从另一个线程调用另一个synchronized方法

    文档也是这样说的:

    当一个线程正在为一个对象执行同步方法时,所有其他调用同一对象块的同步方法的线程(暂停执行)

    所有这一切并不与您可以synchronized并行调用非方法的事实相矛盾,这在实践中会发生。

    • 1

相关问题

  • wpcap 找不到指定的模块

  • 如何以编程方式从桌面应用程序打开 HTML 页面?

  • Android Studio 中的 R.java 文件在哪里?

  • HashMap 初始化

  • 如何使用 lambda 表达式通过增加与原点的距离来对点进行排序?

  • 最大化窗口时如何调整元素大小?

Sidebar

Stats

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

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +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