- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试仅使用等待/通知同步来实现合并排序。我知道更高级的结构,例如 Fork/Join、Executors。等等,但我需要在这里使用工作/通知。基于此https://courses.cs.washington.edu/courses/cse373/13wi/lectures/03-13/我用同步块(synchronized block)重构了方法 parallelMergeSort()
:
public void parallelMergeSort() {
synchronized (values) {
if (threadCount <= 1) {
mergeSort(values);
values.notify();
} else if (values.length >= 2) {
// split array in half
int[] left = Arrays.copyOfRange(values, 0, values.length / 2);
int[] right = Arrays.copyOfRange(values, values.length / 2, values.length);
synchronized(left) {
synchronized (right) {
// sort the halves
// mergeSort(left);
// mergeSort(right);
Thread lThread = new Thread(new ParallelMergeSort(left, threadCount / 2));
Thread rThread = new Thread(new ParallelMergeSort(right, threadCount / 2));
lThread.start();
rThread.start();
/*try {
lThread.join();
rThread.join();
} catch (InterruptedException ie) {}*/
try {
left.wait();
right.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// merge them back together
merge(left, right, values);
}
}
values.notify();
}
}
}
values
是这里的输入数组。
因此,我发现排序的性能下降了,甚至比单线程排序还要慢。我猜想瓶颈在于数组左右部分的两个同步块(synchronized block)内。有人知道如何重构它以使其比单线程排序更快吗?
最佳答案
问题出在您的嵌套同步
block 中:
synchronized(left) {
synchronized (right) {
Thread lThread = new Thread(…);
Thread rThread = new Thread(…);
lThread.start();
rThread.start();
try {
left.wait();
right.wait();
}
…
当您启动新线程时,您将同时持有这两个锁,而新线程又会尝试获取这些锁。因此,您的新线程将被阻塞,直到启动线程释放这些锁。当线程调用 wait()
时,就会隐式发生这种情况 但是 ...您一次只能等待一个条件!
因此,当发起线程调用 left.wait()
时,它会释放 left
实例的锁以及为处理 left 而生成的子线程
部分可以继续,但发起线程在等待left
时仍持有right
锁。一旦子线程完成处理left
,它将调用notify
,然后释放left
的锁,从而允许wait()
重新获取它并返回。
然后启动线程可以调用right.wait()
,这将释放right
锁并允许另一个子线程启动它的工作,因此等于顺序性能。对于子线程的每次生成,由于启动线程持有的锁,子线程都被强制依次运行。
解决此问题的一种方法是首先启动线程,然后获取锁,并且仅获取您要等待
的一个锁,而不是嵌套synchronized
block 。这仍然受到未指定时间的影响(现在,即使在您输入 synchronized(x) { x.wait(); } 之前,子线程可能已经完成其工作并调用
block )和所谓的虚假唤醒。简而言之,您需要一个可验证的条件,在调用 notify
wait()
之前和之后进行检查,如 documentation of wait()
中所述。 :
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
条件可能是子线程在调用 notify()
之前将 boolean
标志设置为 true
以表示工作已完成完成了。
请注意,这一切都是您在使用 Thread.join() 时免费获得的。同步发生在 join()
方法内,并且这两个调用不能重叠。此外,该实现使用可验证的条件(线程的 Activity 状态)来确保仅在必要时调用 wait()
并防止“虚假唤醒”。
关于Java合并排序算法与wait()/notify()同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29492460/
我在一次采访中遇到过这个问题。 线程中wait和wait on time有什么区别? 我知道 wait 方法 导致当前线程等待,直到另一个线程调用此对象的 notify() 方法或 notifyAll
我在这里得到了一个 java 代码片段,这让我想知道调用 wait() 和 this.wait() 之间的区别是什么。 假设您有一个类,该类具有获取资源的方法并且是同步的。通常,如果资源不可用,我会在
我知道如何使用 wait_event 在 Linux 内核队列中等待以及如何唤醒它们。 现在我需要弄清楚如何同时在多个队列中等待。我需要多路复用多个事件源,基本上以类似于 poll 或 select
c系统编程中wait(null)和wait(&status)有什么区别? 指针状态的内容是什么? 最佳答案 如果您调用 wait(NULL) ( wait(2) ),您只会等待任何子进程终止。使用 w
设想: 用户单击 View 上的按钮 这会调用 ViewModel 上的命令 DoProcessing 考虑到 View 和 ViewModel 的职责,Wait 光标是如何以及在哪里设置的? 为了清
我在使用 Selenium 的代码中看到了 FluentWait 和 WebDriverWait。 FluentWait 使用轮询技术,即它将在每个固定时间间隔轮询特定的 WebElement。我想知
我编写了以下代码,其中 start 方法应该等待,直到 stop 方法通知它。但是在执行过程中,尽管我已指定它等待,但启动方法下面的日志行会被打印。下图是我的start方法实现如下。 private
我有以下连接到 SignalR Hub 的代码 private static async Task StartListening() { try {
我对线程中的 wait() 方法如何工作感到很困惑。假设我写: public class test3 { public static void main(String args[]){
在使用 Java 线程原语构造线程安全有界队列时 - 这两种构造之间有什么区别 创建显式锁定对象。 使用列表作为锁并等待它。 示例 1 private final Object lock = new
故事: 在 Java selenium 语言绑定(bind)中有一个 FluentWait class ,这允许严格控制如何检查预期条件: Each FluentWait instance defin
wait-die 和 wound-wait 算法有什么区别? 这两种死锁预防技术似乎都在做同样的事情:回滚旧进程。 两者有什么区别? 请提供一个合适的例子来对比这两种算法。 最佳答案 Wait-Die
在 Java 线程转储中,您可以看到堆栈跟踪中提到的锁。 似乎有三种信息: 1: - locked (a java.io.BufferedInputStream) 2: - waiting to l
以下代码运行大约需要 20 秒。然而,取消注释 do! 后只用了不到一秒的时间。为什么会有这么大的差异? 更新:使用ag.Add时需要9秒。我已经更新了代码。 open FSharpx.Control
我在 ASP.NET WebForms 网站上有一个服务器端点击事件。在这种情况下,我调用一个方法,该方法又调用其异步合作伙伴方法,在调用中添加 .Wait()。 此方法然后向下几个级别(即,调用另一
有 3 种状态的线程处于 Activity 状态但既不运行也不可运行:- sleep 已阻止 正在等待 当线程执行 sleep() 方法时,它会在其参数指定的时间段(比如几毫秒)内从运行状态进入休眠状
考虑以下代码 public class ThreadTest1 { private static final long startTime = System.currentTimeMillis();
我有一个使用线程的 Java 应用程序,它使用多个 Lock 对象实例来同步对公共(public)资源的访问。 现在,作为性能测量的一部分,我想测量每个线程在每个锁中花费的时间。到目前为止,我已经尝试
我写了下面这段代码: let first_row = rows_stream.take(1).wait(); 并收到以下错误(当我真正想要访问该元素时): found struct `futures:
我使用了两个命令来等待设备启动:adb 等待设备和 adb 等待设备。两者似乎都在等待设备启动,我发现它们的行为没有任何区别。他们的行为有什么不同吗? 添加更多关于我所做的信息: 所以这就是我所做的,
我是一名优秀的程序员,十分优秀!