【问题标题】:Why multiple threads are entering the synchronized block?为什么多个线程正在进入同步块?
【发布时间】:2018-07-21 10:17:21
【问题描述】:

我正在编写线程排序程序并且执行有两个方法“prevMethod”和“anotherMethod”在同一个类和同一个监视器共享对象“lock1”中执行,那么为什么两个线程都在同一个同步块中执行,不它违背了监控对象的目的。

class Ordering extends Thread {
    SharedObject obj = null;
    boolean flag = false;

    private AtomicInteger counter;

    Ordering(String name, SharedObject obj, AtomicInteger counter) {
        super(name);
        this.obj = obj;
        this.counter = counter;
    }

    public void run() {
        while (true) {
            prevMethod();
            System.out.println("New Method Started");
            anotherMethod();
        }
    }

    private void prevMethod() {
        synchronized (obj) {
            System.out.println(Thread.currentThread().getName() + " Section 1");
            while (!obj.flag) {
                try {
                    System.out.println(Thread.currentThread().getName() + " "
                            + counter.getAndIncrement());
                    obj.wait();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
            obj.flag = true;
            obj.notify();
        }
    }

    private void anotherMethod() {
        synchronized (obj) {
            System.out.println(Thread.currentThread().getName() + " Section 2");

            while (obj.flag) {

                System.out.println(Thread.currentThread().getName() + " "
                        + counter.getAndIncrement());
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            obj.flag = false;
            obj.notify();
        }
    }
}

public class SequencialPrinting {

    public static void main(String... arg) {
        AtomicInteger counter = new AtomicInteger(3);
        SharedObject lock1 = new SharedObject();
        Thread t1 = new Thread(new Ordering("Thread 1", lock1, counter));
        Thread t2 = new Thread(new Ordering("Thread 2", lock1, counter));
        t1.start();
        t2.start();
    }
}

输出:

Thread-0 Section 1
Thread-0 3
Thread-1 Section 1
Thread-1 4

【问题讨论】:

  • Object.wait() 的 javadoc 是怎么说的?
  • 另外,你的Ordering extends Thread 然后你将new Ordering 传递给另一个Thread。不确定您要达到的目标...
  • 输出没有显示线程同时在块中
  • 如果线程在调用 wait() 时释放锁,那么任何其他线程都可以进入锁定在该锁上的同步块,因为没有其他线程持有它。这就是释放锁的意义所在。如果等待没有释放锁,你怎么能通知线程,因为你需要一个锁来通知?
  • 啊,是的。我懂了。 (但在持有锁的意义上,它们并不是“在块中”。但这就是你的意思。)

标签: java multithreading


【解决方案1】:

第一个线程调用prevMethod(),打印

Thread-0 第 1 节 线程0 3

并调用wait(),然后释放锁。

第二个线程调用 prevMethod()

和打印

Thread-1 第 1 节 线程 1 4

两个线程正在进入同步块。一次只有一个线程进入同步块

【讨论】:

    【解决方案2】:

    我从来没有见过这样的代码......做新线程并将另一个新线程传递给构造函数...... 您应该考虑 1)Ordering 应该只实现 Runnable 或 2)在您的 main 中,只需创建一个新的 Ordering(这是一个线程)并启动它。

    这就是您的代码中发生的情况: “Thread-0”开始执行 prevMethod,当它命中同步语句时,它得到了监视器(它现在拥有它)。 (“Thread-1”现在可能已经停留在同一个同步语句上)无论如何,“Thread-0”打印了“Thread-0 Section 1”和“Thread-0 3”。然后它在监视器上执行等待。 wait 放弃监视器,所以现在“Thread-0”已经放弃了监视器,正在等待通知。现在“Thread-0”不再是监视器的所有者,它可以被分配给卡在同步语句上的“Thread-1”。现在“Thread-1”通过同步语句(成为共享 obj 的所有者)并打印出 enxt 2 行,然后也放弃了监视器......

    【讨论】:

    • 考虑格式化你的答案是一种比难以理解的块样式更令人愉快的方式。此外,值得用一些关于wait 行为方式的文档来支持您的解释。最后,您的第一段确实是旁白——OP使用Thread作为Runnable传递给另一个Thread的事实真的很奇怪,并不重要——这样对待它,把评论放在您的答案的结尾,也许还有改进的建议。
    • 用糟糕的答案回答糟糕的(被否决的)问题可能只会吸引你的答案的投票者。
    • 有趣的是,由于样式和格式,忽略了实质,此答案导致了负面反馈,实际上它包含此答案之后的所有其他答案
    猜你喜欢
    • 1970-01-01
    • 2015-03-02
    • 2013-09-12
    • 1970-01-01
    • 2012-02-05
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    相关资源
    最近更新 更多