相关疑难解决方法(0)

GCD调度并发队列冻结,崩溃日志中的"Dispatch Thread Soft Limit Reached:64"

我的程序是一个处理传入请求的服务器.每个有效请求都被包装NSOperation并传递给法线NSOperationQueue.

每个都NSOpearation处理它的请求.在某些情况下,NSDictionary我使用dispatch_queue(并发队列),dispatch_barrier_async(当设置值时)和dispatch_sync(当获取值时)存在争用,以使此NSDictionary线程安全.

我同时用100个请求测试我的程序,然后该过程有时冻结.我用SIGSEGV查看崩溃日志来终止进程.

大多数线程都停留在dispatch_sync此队列中.下面有一张纸条

达到调度线程软限制:64(同步操作中阻塞的调度线程太多)

这个音符到底意味着什么?它的行为是什么?我找不到有关此限制的信息.我该如何解决这个问题?

我可以想出两种可能的方法来避免这个问题.(我将测试它们并稍后更新)

  1. 使用dispatch_semaphore限制块提交给该并发队列.
  2. 限制maxConcurrentOperationCountNSOperationQueue

你有更好的解决方案吗?

multithreading grand-central-dispatch

6
推荐指数
1
解决办法
1513
查看次数

一次多次调用DispatchSemaphore的wait()是否安全?

我得到了三个名为queueA,queueB,queueC的调度线程。
现在,我希望在执行queueB和queueC之后执行queueA。
所以我尝试通过实现它DispatchSemaphore
我的问题是:一次在线程中两次
调用wait()以使信号量2安全吗?

 self.semaphore.wait()  // +1
 self.semaphore.wait()  // +1
Run Code Online (Sandbox Code Playgroud)

以下是完整的测试代码:

class GCDLockTest {
    let semaphore = DispatchSemaphore(value: 0) 

    func test() {

        let queueA = DispatchQueue(label: "Q1")
        let queueB = DispatchQueue(label: "Q2")
        let queueC = DispatchQueue(label: "Q3")
        queueA.async {
            self.semaphore.wait()  // +1
            self.semaphore.wait()  // +1
            print("QueueA gonna sleep")
            sleep(3)
            print("QueueA woke up")                
        }
        queueB.async {
            self.semaphore.signal()  // -1
            print("QueueB gonna sleep")
            sleep(3)
            print("QueueB woke up")

        }
        queueC.async {
            self.semaphore.signal()  // -1
            print("QueueC gonna sleep") …
Run Code Online (Sandbox Code Playgroud)

grand-central-dispatch swift swift4

6
推荐指数
2
解决办法
3687
查看次数

在Swift中使用libevent和GCD(libdispatch)

我正在Swift 3中创建一个服务器端应用程序.我选择了libevent来实现网络代码,因为它是跨平台的并且不会遇到C10k问题.Libevent实现了它自己的事件循环,但我想保持CFRunLoop和GCD(DispatchQueue.main.after等)功能,所以我需要以某种方式粘贴它们.

这就是我想出的:

var terminated = false

DispatchQueue.main.after(when: DispatchTime.now() + 3) {
    print("Dispatch works!")
    terminated = true
}

while !terminated {
    switch event_base_loop(eventBase, EVLOOP_NONBLOCK) { // libevent
    case 1:
        break // No events were processed
    case 0:
        print("DEBUG: Libevent processed one or more events")
    default: // -1
        print("Unhandled error in network backend")
        exit(1)
    }
    RunLoop.current().run(mode: RunLoopMode.defaultRunLoopMode,
                          before: Date(timeIntervalSinceNow: 0.01))
}
Run Code Online (Sandbox Code Playgroud)

这有效,但引入了0.01秒的延迟.当RunLoop正在休眠时,libevent将无法处理事件.当应用程序空闲时,降低此超时会显着增加CPU使用率.

我也在考虑只使用libevent,但是项目中的第三方库可以在内部使用dispatch_async,因此这可能会有问题.

在另一个线程中运行libevent的循环会使同步变得更加复杂,这是解决此延迟问题的唯一方法吗?

LINUX更新.上面的代码在Linux上不起作用(2016-07-25-a Swift snapshot),RunLoop.current().run存在错误.下面是一个工作的Linux版本,重新实现了计时器和dispatch_main.它遇到了相同的延迟问题:

let queue = dispatch_get_main_queue()
let timer = …
Run Code Online (Sandbox Code Playgroud)

network-programming libevent grand-central-dispatch swift swift3

5
推荐指数
1
解决办法
547
查看次数

如果我想在后台运行任务,"dispatch_get_global_queue"队列如何工作?

在选择要运行的队列dispatch_async时,dispatch_get_global_queue会提到很多.这是一个特殊的后台队列,它将任务委托给某个线程吗?它几乎是一个单身人士吗?

因此,如果我总是将该队列用于我的dispatch_async调用,那么该队列是否会变满并且必须等待其他事情才能启动,或者是否可以将其他任务分配给不同的线程?

我想我有点困惑,因为当我选择队列时NSOperation,我可以选择主线程的队列[NSOperationQueue mainQueue],这似乎是同义词,dispatch_get_main_queue但我在印象背景队列下NSOperation不得不单独制作实例NSOperationQueue但是GCD有一个背景队列单例?(dispatch_get_global_queue)

此外 - 愚蠢的问题,但想确保 - 如果我将一个任务放入队列,队列被分配给一个线程,对吧?如果任务足够大,它就不会在多个线程上拆分,是吗?

multithreading objective-c nsoperation grand-central-dispatch ios

2
推荐指数
1
解决办法
412
查看次数