如果 Java 线程在这种情况下不应该表现得如此不同,为什么它们的行为如此不同?

2024-01-12

我有线程睡眠问题。在线程运行方法内部,我有一个同步块和一个睡眠时间。 每个线程以 5 个单位递增或递减共享类“值”,然后休眠。

public class borr {

    public static void main(String[] args) {

        int times=5;
        int sleeptime=1000;
        int initial=50;
        Shared shared = new Shared(initial);

        ThreadClass tIncrement = new ThreadClass(shared,times,sleeptime,true);
        ThreadClass tDecrement = new ThreadClass(shared,times,sleeptime,false);
        tIncrement.start();
        tDecrement.start();
    }
}

class Shared{

    int  value=0;

    public Shared(int value) {
        super();
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

class ThreadClass extends Thread{

    Shared shared;
    int times=0;
    int sleeptime=0;
    boolean inc;

    public ThreadClass(Shared shared, int times, int sleeptime, boolean inc) {
        super();
        this.shared = shared;
        this.times = times;
        this.sleeptime = sleeptime;
        this.inc = inc;
    }

    public void run() {

        int aux;

        if(inc) {
            for(int i=0;i<times;i++) {
                synchronized(shared) {
                    aux=shared.getValue()+1;
                    shared.setValue(aux);
                    System.out.println("Increment, new value"+shared.getValue());

                    try {
                        Thread.sleep(sleeptime);
                    }catch(Exception e) {
                        e.printStackTrace();
                    }
                }
            }   
        }
        else {
            for(int i=0;i<times;i++) {
                synchronized(shared) {
                    aux=shared.getValue()-1;
                    shared.setValue(aux);
                    System.out.println("Decrement, new value"+shared.getValue());

                    try {
                        Thread.sleep(sleeptime);
                    }catch(Exception e) {
                        e.printStackTrace();
                    }
                }
            }   
        }
    }
}

但如果我移动Thread.sleep出于synchronizedblock,像这样,输出是递增,递减,递增,递减。当它停止休眠并开始新的循环迭代时,其他线程不应该尝试进入吗?相反,它继续循环直到该线程完成:

for(int i=0;i<times;i++) {
    synchronized(shared) {
        aux=shared.getValue()-1;
        shared.setValue(aux);
        System.out.println("Decrement, new value"+shared.getValue());
    }

    try {
        Thread.sleep(sleeptime);
    }catch(Exception e) {
        e.printStackTrace();
    }
}   

这不好:

for(...) {
    synchronized(some_lock_object) {
        ...
    }
}

它不好的原因是,一旦某个线程 A 进入该循环,那么每次它解锁锁时,接下来的事情它所做的就是再次锁定锁。

如果循环体花费大量时间来执行,则等待锁的任何其他线程 B 将被操作系统置于等待状态。每次线程 A 释放锁时,线程 B 都会开始唤醒,但线程 A 将能够在线程 B 有机会之前重新获取锁。

这是一个经典的例子饥饿 https://en.wikipedia.org/wiki/Starvation_(computer_science).

解决该问题的一种方法是使用ReentrantLock https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html with a 公平订购政策 https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html#ReentrantLock-boolean-而不是使用synchronized堵塞。当线程竞争公平锁时,获胜者总是等待时间最长的线程。

但是,公平锁的实施成本很高。更好的解决方案是始终保留任何人的身体synchronized块尽可能短且尽可能甜。通常,线程保持锁锁定的时间不应超过在某个对象中分配少量字段所需的时间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果 Java 线程在这种情况下不应该表现得如此不同,为什么它们的行为如此不同? 的相关文章

随机推荐

  • SUMIFS) 与 VLOOKUP

    我正在尝试将 VLOOKUP 函数与 sumif 函数一起使用 我有一个下拉框 其中包含名称列表和组合列表 e g Salesman1 Salesman2 Salesman3 Salesman4 Salesman5 Salesman6 Re
  • 如何配置发布配置文件以使用 NTLM 身份验证

    在 Visual Studio 2012 中 使用发布配置文件和 Web 部署大大简化了部署 然而它仍然缺少一些东西 或者可能我还不知道如何使用它 我更喜欢使用 NTLM 身份验证 而不将用户名和密码 尤其是 存储在发布配置文件中 如何才能
  • 批处理文件中的子程序

    给出以下代码 Echo off ECHO Start ECHO Calling SUB A CALL SUB A ECHO Calling SUB B CALL SUB B SUB A ECHO In SUB A GOTO EOF SUB
  • Mac 光标文件夹

    我已经研究了几个小时了 我想找到我的 Mac 系统默认光标 没有任何鼠标悬停 我只想要默认光标 我正在运行旧版本的 Mac 之一 即 10 4 11 有人告诉我光标在这里 System Library Frameworks Applicat
  • mysql SELECT NOT IN () -- 不相交集?

    我在查询工作时遇到问题 我认为这应该有效 它的形式是 SELECT DISTINCT a b c FROM t1 WHERE NOT IN SELECT DISTINCT a b c FROM t2 AS alias 但是 mysql 在
  • 收到内存警告和应用程序崩溃[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 由于收到内存警告 我的应用程序崩溃了
  • git 仅推送一个文件到 Heroku

    是否可以只将一个文件推送到 Heroku 而不是关闭所有已更改的文件 谢谢 不会 Git 跟踪内容而不是文件 因此您要么推送全部内容 要么不推送任何内容 如果有您不想推送的文件 请将它们添加到 gitignore文件 但是 如果您已经提交了
  • C_CPP.intellisense 已禁用。如何再次启用

    我在 Visual Studio 代码中尝试过的扩展似乎禁用了 C C 智能感知 无法再次开启 修改设置对话框中的设置没有任何效果 证据 切换源 标头会导致弹出消息 指出 C CPP intellisense 设置为禁用 现在花了几个小时
  • 我可以为 localhost 配置 cron 作业吗

    这是一个单行问题 我不知道如何描述它 mysystem config os windows Xp server Wamp server latest 这可能吗 Cron 是类 Unix 计算机操作系统中基于时间的作业调度程序 这意味着您无法
  • 为什么 OpenMP 缩减子句对于静态调度循环是不确定的?

    我一直在从事一个多 GPU 项目 在该项目中我在获得非确定性结果方面遇到了问题 当我发现由于 CPU 上执行的归约子句而获得非确定性结果时 我感到很惊讶 在书里使用 OpenMP 下一步据说 线程组合其值来构建的顺序 共享结果的价值是不确定
  • 有没有办法拦截和修改asp.net中的html输出流,以结合javascript?

    有没有办法拦截asp net中的HTML输出流并进行修改 例如使用httpmodules之类的 我知道使用 java servlet 是可能的 并且假设必须有一种优雅的方法来使用 ASP NET 来做到这一点 我的目的是将许多 JavaSc
  • 如何为 pytest 测试类的所有方法共享同一个实例

    我有一个简单的测试课 pytest mark incremental class TestXYZ def test x self print self def test y self print self def test z self p
  • JPA:OptimisticLockException 和级联

    在我当前的项目中 我将 Spring Data JPA 与 Hibernate 结合使用 但将此视为一个更普遍的问题 也应该涵盖 普通 JPA 我不确定我应该如何处理OptimisticLockException使用时 Version 由于
  • 如何修复 FileNotFoundError: [WinError 2] 系统找不到 AudioSegment.from_mp3() 指定的文件

    我一直在尝试找到视频音频中音频静音空间的位置 但我无法通过在 python 3 中使用 pydub 导入音频文件 我已经尝试将 pydub 检查 ffmpeg 的目录更改为项目内的目录 并且该文件位于我运行脚本的目录中 但它似乎仍然返回相同
  • GitLab 页面:可以从项目 wiki 生成静态站点吗?

    所以我知道 GitLab 页面可用于从项目的存储库生成静态网站 然而 我想做的是从项目生成一个静态站点wiki 这是一个单独的存储库 我还知道我可以将静态站点生成器挂钩到 webhook 事件以通知 wiki 更改 我正在尝试弄清楚这个明显
  • jQuery - 是否可以复制和粘贴 HTML?

    jQuery 是否可以复制和粘贴 HTML 从一个例子开始 如果我有以下 HTML 行 div somethings like 100 lines of code div 我想知道我是否可以将此 div 复制并粘贴多次 我尝试放置一个 jQ
  • 永久添加 hive jar

    有什么方法可以永久添加 hive jar 而不是在 hive shell 中的会话级别添加 任何帮助 将不胜感激 在 hiveserver2 主机中 创建一个类似 var lib hive 的位置 并在该文件夹中添加所有必需的 jar 编辑
  • 检查项目是否重叠

    我有几个房间是随机放置的 所以我必须检查房间是否重叠 房间的大小为 10x10 出于测试原因 房间完全并排放置 它们在场景中不重叠 地板是一种变换 由 1 个或多个变换组成 在本例中 由一个正方形组成 但对于其他形式 它可能是 2 个或更多
  • Python互相关未返回正确的移位

    我正在学习互相关 为此我在一些简单的示例上运行 scipy signal correlate 然而 在某些情况下 相关函数的最大值与输入时移不一致 即使正确的时移存在于dt 我怀疑问题在于我的定义dt 但经过几次迭代后 我还没有设法使转变始
  • 如果 Java 线程在这种情况下不应该表现得如此不同,为什么它们的行为如此不同?

    我有线程睡眠问题 在线程运行方法内部 我有一个同步块和一个睡眠时间 每个线程以 5 个单位递增或递减共享类 值 然后休眠 public class borr public static void main String args int t