ThreadPoolExecutor 中的竞争条件

问题描述 投票:0回答:1

什么代码必须执行:

  • 同步执行
    Bot#run

需要修复什么:

  • 在其他机器人和线程之间共享资源 (
    Bot.responseData or.. more
    )。

Bot.run()执行阶段:

  1. http 请求 -> 从服务器获取随机值(如 f8c3de3d-1fea-4d7c-a8b0-29f63c4c3454)。 (服务器始终返回随机值!)
  2. 将值保存至
    Bot.responseData
  3. http 请求(使用
    Bot.responseData
    作为参数)-> 返回 JSON。
  4. 将 JSON 保存到
    Bot.statistics
  5. 清理
    Bot.responseData = null

机器人实体:

public class Bot 
{
    private final BotStatistic statisic = new BotStatistic();
    private final Object mutex = new Object();
    private String responseData;    

    void run() 
    {
        synchronized(mutex) 
        {
          String myHost = "http://myhost";
          firstCall(myHost)
          secondCall(myHost);
          cleanup();
        }
    }

    private void firstCall(String host) 
    {
        // first http call -> responseData = "f8c3de3d-1fea-4d7c-a8b0-29f63c4c3454";
    }

    private void secondCall(String host) 
    {
        // second http call(responseData) -> 
        // JSON {"success": true, "requestValue": "f8c3de3d-1fea-4d7c-a8b0-29f63c4c3454"}
        statistic.add(json);
    }

    private void cleanup() 
    {
        this.responseData=null;
    }
}

BotRunner 实体:

public class BotRunner implements Runnable 
{
    private final Bot bot;
    
    public BotRunner(Bot bot) 
    {
        this.bot = bot;
    }
    
    @Override
    public void run() 
    {
       bot.run();
    }
}

尝试这样执行:

//init executor
LocalDateTime termination = LocalDateTime.now().plusSeconds(5L);
while (LocalDateTime.now().isBefore(termination)) 
{
    for (Bot bot : bots) 
    {
        executor.execute(new BotRunner(bot));
    }
}
//shutdown & close executor

我现在所看到的

执行后,我看到 1-2% 的重复

Bot.responseData
来自不同的
Bot
。诸如此类的事情:

thread-1 : start (Bot@44g35)
thread-1 : f8c3de3d-1fea-4d7c-a8b0-29f63c4c3454
thread-2 : start (Bot@898g)
thread-2 : f8c3de3d-1fea-4d7c-a8b0-29f63c4c3454
thread-1 : end
thread-2 : end

我必须看到什么

thread-1 : start (Bot@44g35)
thread-1 : f8c3de3d-1fea-4d7c-a8b0-29f63c4c3454
thread-2 : start (Bot@898g)
thread-2 : 018b2f19-e79e-7d6a-a56d-29feb6211b04
thread-1 : end
thread-2 : end

如果有人可以帮助我,我将非常感激:)

java multithreading concurrency executorservice synchronized
1个回答
0
投票

你的代码不完整,所以我不能确定 - 但你必须在线程之间共享一个变量。

根据您提供的代码片段,

Bot
类是不是线程安全的
responseData
是共享的)。我很好奇为什么你会尝试用 20 年的方法来解决线程安全问题,比如
synchronized(mutex)
;如果您的机器人线程确实没有共享,则没有必要这样做。 (更现代的方法是使用Lock)。

您如何创建机器人集合?这些都是不同的实例吗?

或者您如何进行 HTTP 调用 - 该代码是线程安全的吗?

正如@tgdavies 所说,你如何进行输出?

© www.soinside.com 2019 - 2024. All rights reserved.