当前位置: 首页 > 知识库问答 >
问题:

从不同步方法进行呼叫时发出 [已关闭]

姬昀
2023-03-14

编辑问题,以包括预期行为、特定问题或错误以及重现问题所需的最短代码。这将有助于其他人回答问题。

为什么以下代码不能保证多个线程之间total_home数量的唯一性,即使逻辑位于同步块中也是如此。

class Country {
    private static int home = 0;
    int total_home;

    private static synchronized int counter() {
        return ++home ;
    }

    public void getTotal() {
        total_home = counter(); System.out.println(total_home);

    }
}

public class T1 extends Thread {

private Country c;

public T1(Country c) {
    this.c = c;
}

@Override
public void run() {
    for (int i = 0; i <= 10; i++)
        c.getTotal();
}

}

public class T2 extends Thread {

private Country c;

public T2(Country c) {
    this.c = c;
}

@Override
public void run() {
    for (int i = 0; i <= 10; i++)
        c.getTotal();
}

}

public class MainClass {
public static void main(String[] args) {
    Country c = new Country();
    T1 ok = new T1(c);
    T2 ok1 = new T2(c);
    ok.start();
    ok1.start();
}

}

这是一个程序示例。试着运行5-10次,你会发现total_home的值每次都不唯一。

共有1个答案

贺福
2023-03-14

您的代码具有:

Country c = new Country();
   T1 ok = new T1(c);
   T2 ok1 = new T2(c);
   ok.start();
   ok1.start();

这应该是显而易见的:计算新国家/地区在代码中执行的次数。它。。一次。

因此,一般来说,只有一个国家对象可用。你的第一个和第二个线程都在引用它。(这类似于:他们都有一个唯一的地址簿。但是这两本书的地址是一样的。java中的所有对象变量都是引用)。

您的同步代码不是问题,这工作正常 - 每次调用 counter() 都会返回一个唯一的值。

但是,您有 2 个线程都在调用您创建的完全相同的单个国家/地区对象上的 getTotal()

ok.cok2.c 是相同的(它们指的是同一个对象)。因此,它们当然具有相同的total_home值 - 系统中只有一个total_home,并且您每次都会覆盖它。

代码中还有更多内容表明您需要对java的工作原理进行更多审查。例如,类 T1类 T2 是完全相同的 - 那么为什么你有这些呢?

我想,这是你打算写的东西:

public static void main(String[] args) throws Exception {
  Country c1 = new Country();
  Country c2 = new Country();
  T1 ok1 = new T1(c1);
  T1 ok2 = new T1(c2);
  ok1.start();
  ok2.start();
  System.out.println("These are guaranteed different: " + c1.total_home + " " + t2.total_home);
}

注意:目前有一个投票赞成的评论,表明你的静态int home变量“可能”被缓存,你应该添加不稳定的变量。这是不正确的 - 同步足以消除所有争用条件。然而,AtomicInteger在这里是一个更好的选择 - 同步是一个相当“昂贵”的措施,AtomicInteger为您提供了一个有保证的唯一计数器,使用显着“更快”的原语(它不使用锁,它使用CPU的比较和设置(CAS)基础架构,这是快几个数量级)。

 类似资料:
  • 我有3个类:主要游戏,ufoMovement(实际上是一个线程)和ufo本身(是的,在图片中是德语,但他们只是名字)。UfoMovement创建了一个Ufo,它有一个叫做“爆炸”的方法,其中组件会飞离。主游戏开始线程UFOMovement。这个游戏是一个小行星躲避游戏,你的ufo正在飞行,你必须躲避小行星,这意味着我必须从main类调用方法:Explomde,因为那个类检查碰撞,但是当我调用mai

  • 我正试着从我的twilio试用帐户拨出电话。我指的是这个链接。基于这个链接,我创建了一个名为hello-client-twiml.php的页面,代码如下: 有人能帮我解决这个问题吗?提前谢了。

  • 这里是Twilio的新手,并寻求twilio专家的建议。我正在尝试拨打IVR系统的出站电话,等待几秒钟并发送键盘号码输入以在另一端启动工作流程 到目前为止,我可以呼叫IVR系统,但我如何发送号码输入?我认为TwiML是实现这一点的方法!非常感谢您的帮助

  • 我在调用我的onLeScan时遇到问题。我在开始扫描中放置了一个标签,每次都会被调用。出于某种原因,我的onLeScan永远不会被调用。有人看到我所做的有问题吗?onLeScan应该在开始扫描后立即调用,对吗? 编辑更改了我的onLeScan函数。仍然不起作用,但我认为我正在走向正确的道路。DeviceBeacon是一个只包含方法的类:getName()、getSignal()和getAddres

  • 问题内容: 我希望在后台使用jQuery作为“心跳”进行AJAX调用,以便我的Web应用程序可以检查新数据。例如,每10秒。 我在其他帖子上看到,可以使用调用每X毫秒进行一次调用的方法。 但是,如果我的AJAX通话时间超过10秒怎么办?我仍然希望它完成上一个请求,并且当正在进行中的一个请求时,我不希望发出另一个呼叫。这可能导致相同的信息两次被放置到页面上! 当我的方法等待原始AJAX调用完成时,而

  • 是否有一个gradle插件或任何其他方法调用hiberNate工具hbm2ddl任务来从注释的类生成数据库模式,而不必列出一些配置文件中的所有实体(@Entity),但在类路径中发现它们? 最好是针对Hibernate5,但Hibernate4也可以。