当前位置: 首页 > 面试题库 >

同步块不起作用

万俟震博
2023-03-14
问题内容

该练习直接由Kathy Seirra和Bert Bates撰写的SCJP

同步代码块

在本练习中,我们将尝试同步代码块。在该代码块中,我们将获得对对象的锁定,以便在代码块执行时其他线程无法修改它。我们将创建三个线程,它们都将尝试操纵同一对象。每个线程将输出一个字母100次,然后将该字母加1。我们将使用的对象是StringBuffer。

我们可以在String对象上进行同步,但是一旦创建字符串就无法对其进行修改,因此如果不生成新的String对象,我们将无法递增字母。最终输出应具有100
As,100 Bs和100 Cs的连续线。

  1. 创建一个类并扩展Thread类。
  2. 重写Thread的run()方法。这是同步的代码块将要去的地方。
  3. 为了使三个线程对象共享同一对象,我们需要创建一个构造函数,该构造函数在参数中接受StringBuffer对象。
  4. 同步的代码块将从步骤3获得对StringBuffer对象的锁定。
  5. 在该块内,输出StringBuffer 100次,然后递增StringBuffer中的字母。您可以在第6章中找到有关StringBuffer方法的信息,这将对此有所帮助。
  6. 最后,在main()方法中,使用字母A创建单个StringBuffer对象,然后创建类的三个实例并启动所有三个实例。

我为上述练习编写了以下课程(而不是100,我正在打印10个字符)

class MySyncBlockTest extends Thread {

    StringBuffer sb;

    MySyncBlockTest(StringBuffer sb) {
        this.sb=sb;
    }

    public static void main (String args[]) {
        StringBuffer sb = new StringBuffer("A");
        MySyncBlockTest t1 = new MySyncBlockTest(sb);
        MySyncBlockTest t2 = new MySyncBlockTest(sb);
        MySyncBlockTest t3 = new MySyncBlockTest(sb);
        t1.start();
        t2.start();
        t3.start();
    }

    public void run() {
        synchronized(this) {
            for (int i=0; i<10; i++) {
                System.out.print(sb);
            }
            System.out.println("");
            if (sb.charAt(0)=='A')
                sb.setCharAt(0, 'B');
            else
                sb.setCharAt(0, 'C');
        }
    }
}

我期望输出类似以下内容(10 As,10 Bs和10 Cs),但没有得到。

AAAAAAAAAA
BBBBBBBBBB
CCCCCCCCCC

相反,我得到了如下所示的变化输出,因为三个线程在另一个线程完成之前有机会进入循环。

AAAAAAAAAAAAAAAAAA
ABB
ACCCCCCCC

我的问题是为什么run方法中的同步块不起作用?


问题答案:

4.同步的代码块将从步骤3获得对StringBuffer对象的锁定。

好吧,你不是那样做的,对吗?

synchronized(this) {

您正在获得对其上调用MySyncBlockTestrun()方法的实例的锁定。那……什么都不会做。该资源无可争辩;每个Thread都有自己的实例MySyncBlockTest



 类似资料:
  • 这个练习直接来自SCJP,由凯西·塞拉和伯特·贝茨完成 同步代码块 在这个练习中,我们将尝试同步一个代码块。在该代码块中,我们将获得对象的锁,以便其他线程在代码块执行时无法修改它。我们将创建三个线程,它们都将尝试操作同一对象。每个线程将输出一个字母100次,然后将该字母递增一次。我们将使用的对象是StringBuffer。 我们可以在一个String对象上进行同步,但是字符串一旦创建就不能被修改,

  • 我们在银行有100个账户和两个办事员,作为线程实现,他们使用同步方法transferMoney将每1000倍的资金从accountNumberFrom账户转移到accountNumberTo账户。由于所有账户都以余额0开头,并且从一个账户取回的资金被转移到另一个账户,因此在所有交易之后,余额应该为零。大多数时候都是这样,但并不总是这样。虽然很少发生,但有时交易后的余额不等于0。怎么了?

  • 问题内容: 我正在尝试同步三个线程以打印012012012012…。但是它不能正常工作。每个线程都分配有一个编号,当它从主线程接收到信号时将打印该编号。以下程序有问题,我无法捕获。 问题答案: 您需要更多的协调。该notify调用不会立即唤醒线程并强制其继续执行。相反,您可以考虑notify将电子邮件发送给线程以使其可以继续进行。想象一下,如果您想让3个朋友按顺序给您打电话。您向朋友1发送了一封电

  • 我正在尝试与selenium webDrive同步,但某些东西无法隐含地使用等待()。 我隐含理解的方式等待(...)是代码正在等待,直到元素在最大时间内可用。 以下代码因错误而崩溃: 系统。out ist打印:-- 我也用Geckodriver试过了,结果也一样。 我也增加了等待时间,但结果相同。 使其工作的唯一方法是使用Thread.sleep()(上面评论) 编辑请注意,我没有看到任何重复与

  • 运行之后(在jdk1.8中),答案不是1000。请告诉我原因。

  • 问题内容: 我正在查看包含同步方法的第三方库中的一些代码,在此方法中,有一个锁定在实例变量上的同步块。与此类似: 这有意义吗?如果是这样,在同步方法中使用同步语句有什么好处? 鉴于同步方法锁定了整个对象,对我来说似乎是多余的。在使用非私有的实例变量时,这种方法是否有意义? 问题答案: 在您的示例中,该方法 同时 锁定了和的实例。其他方法可能仅锁定对象的实例 或 对象。 因此,是的,这完全取决于他们