【问题标题】:How to make thread safe code block in swift如何在swift中制作线程安全的代码块
【发布时间】:2018-08-10 07:08:39
【问题描述】:

我尝试了 stackoverflow 上给出的多个解决方案/答案,但没有一个对我有用。其中一些如下:

https://stackoverflow.com/a/30495424/3145189

Is this safe to call wait() of DispatchSemaphore several times at one time?

https://stackoverflow.com/a/37155631/3145189

我正在尝试实现非常简单的事情,代码块或函数应该串行执行,无论它是从哪个线程调用的。

我的示例代码:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

   DispatchQueue.global().async {
        self.testLog(name:"first")
    }
    DispatchQueue.global().async {
        self.testLog(name:"second")
    }

    DispatchQueue.main.async {
        self.testLog(name: "mainthread")
    }
}


func testLog(name:String) -> Void {
        for i in 1..<1000 {
            print("thread test \(i) name =\(name)")
        }

    }

所以输出应该是 -

第一个线程调用

线程测试 1 名称 =first

线程测试 2 名称 =first

线程测试 3 名称 =first

.

.

.

线程测试 999 名称 =first

第二个线程调用

线程测试 1 名称 =second

线程测试 2 名称 =second

.

.

.

线程测试 999 名称 =second

主线程调用

线程测试 1 名称 =mainthread

线程测试 2 名称 =mainthread

.

.

.

线程测试 999 名称 =主线程

如果函数在第一个线程上被调用,它应该只为第一个线程继续打印日志。线程的顺序可能会有所不同我不在乎意味着即使它首先打印主线程日志然后是第二个和第一个无关紧要的日志应该被分组。

【问题讨论】:

  • 我尝试了多种方法,但在我的问题的示例代码中未提及,因此请您在发布前测试您的答案
  • 创建一个串行队列并将 testLog() 添加到队列中。

标签: ios swift xcode multithreading locking


【解决方案1】:

这将串行执行调用。 保留对serialQueue 的引用,您可以从任何线程提交块。

let serialQueue = DispatchQueue(label: "serial_queue")

    serialQueue.async {
        self.testLog(name: "first")
    }
    serialQueue.async {
        self.testLog(name: "second")
    }

    serialQueue.async {
        self.testLog(name: "third")
    }

【讨论】:

  • 可以做like-> serialQueue.async { self.testLog(name: "first") self.testLog(name: "second") self.testLog(name: "third") } in one仅限异步块。
  • 确实如此,但我试图演示每个async 调用可以从代码中不同位置的不同线程进行
【解决方案2】:

我正在尝试实现非常简单的事情,代码块或函数应该串行执行,无论它是从哪个线程调用的。

要串行执行,请使用 Dispatch 串行队列。如果您正在编写一个类或结构,您可以在类/结构级别使用static let 来存储您的序列化函数可以分派到的队列。在这种情况下,static let 相当于某些语言中的“类变量”。

如果您使用 (Objective-)C 编写此类变量,也可以在函数级别声明,即具有全局生命周期但作用域仅限于函数内的变量。 Swift 不支持在函数中使用这些,但您可以将结构限定为函数...

func testLog(name:String) -> Void
{
   struct LocalStatics
   {
      static let privateQueue = DispatchQueue(label: "testLogQueue")
   }

   // run the function body on the serial queue - could use async here
   // and the body would still run not interleaved with other calls but
   // the caller need not wait for it to do so 
   LocalStatics.privateQueue.sync {
      for i in 1..<1000
      {
         print("thread test \(i) name =\(name)")
      }
   }
}

(有关 Swift 中“局部静态”的辩论,请参阅 this SO Q&A

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多