我是swift的新手,我正在尝试使用多线程技术,这个概念在swift中似乎并不出名。根据java synchronized
实现的this示例,我尝试根据为another SO帖子上的swift提供的示例为swift做同样的事情。这是我的实施:
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
public class TestThread {
var name : String;
var theDemo : TheDemo;
init(_ name : String, _ theDemo : TheDemo) {
self.theDemo = theDemo;
self.name = name;
run()
}
public func run() {
DispatchQueue.global(qos: .background).async {
DispatchQueue.main.async {
self.theDemo.testSynced(self.name)
}
}
}
}
public class TheDemo {
private func synced(_ lock : Any, _ name : String, _ closure : (_ name : String) -> ()){
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
closure(name)
}
public func testSynced(_ name : String){
synced(self, name, test)
}
public func test(_ name : String) {
for i in 0..<4 {
let str = "\(name) :: \(i)"
let theDeadline = DispatchTime.now() + .seconds(i/2)
DispatchQueue.main.asyncAfter(deadline: theDeadline, execute: {
print(str)
})
}
}
}
var theDemo = TheDemo()
TestThread("THREAD 1", theDemo)
TestThread("THREAD 2", theDemo)
TestThread("THREAD 3", theDemo)
TestThread("THREAD 4", theDemo)
当我在操场上运行上面的代码时,我得到的结果如下所示
THREAD 1 :: 0
THREAD 1 :: 1
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 4 :: 0
THREAD 4 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 4 :: 2
THREAD 4 :: 3
但我期待的结果如下所示。
THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 4 :: 0
THREAD 4 :: 1
THREAD 4 :: 2
THREAD 4 :: 3
我希望了解我做错了什么。考虑到同步和快速线程的概念,我是否也在正确的道路上设定了我的期望。我很感激帮助。感谢。
修改
由于我认为自己被误解了,所以我想解释一下我想做的事情。我基本上想要实现的是与我在代码中所写的有点不同。这是一个简化版本。如果synchronized
在一个简单的例子中工作,我想测试它,然后我想在另一个项目中使用它。我正在将为android编写的项目翻译成ios。在java多线程中,我使用synchronized
,因此一次只有一个线程可以使用该函数。让我们说多个线程可以使用的变量或函数。当我在函数名或变量名之前放置synchronized时,线程将有一个锁。现在在我的项目中,我有几个线程,基于一些传感器输入来来去去 - 在它们死之前它们使用了一个共同的共享功能。他们可以随时来。由于多种原因,我们设置了常用函数synchronized
,以便没有两个线程同时进入该函数。因此,当我翻译代码时,我在swift中查找了类似的内容,并找到了与此问题相关联的链接之一。我尝试使用它 - 它对我没用。错误是人 - 我可能在某处犯了错误。但我花时间根据我的日程安排阅读。 (我部分地说多线程在swift中并不是很有名,因为我读过一些地方this)
答案 0 :(得分:1)
在TheDemo
let theDeadline = DispatchTime.now() + .seconds(i/2)
DispatchQueue.main.asyncAfter(deadline: theDeadline, execute: {
self.theDemo.testSynced(self.name)
在TestThread
:
DispatchQueue.global(qos: .background).async {
let theDeadline = DispatchTime.now() + .seconds(1)
DispatchQueue.main.asyncAfter(deadline: theDeadline, execute: {
在TheDemo
for i in 0..<4 {
let str = "\(name) :: \(i)"
print(str)
}
因此。每个异步任务都完成得非常快,以至于它们从现在起被推迟到同一时间。您可以深入了解DispatchQueue的主线程如何在您同时执行所有操作时处理这种情况。
//Starts at some exact time
TestThread("THREAD 1", theDemo)
TestThread("THREAD 2", theDemo)
TestThread("THREAD 3", theDemo)
TestThread("THREAD 4", theDemo)
//Finishes at the same exact time. Too fast!
//
在我的解决方案中,打印是在单个时间上下文中(操作员的主队列,您可以在其中创建所有自定义线程)。因此它按照您的预期打印。您将不得不使用更精细的单位(没有[纳秒])或设计它与我向您展示的略有不同。
答案 1 :(得分:1)
首先,不要在操场上测试这些东西,因为它的输出不能正确模拟现实。在实际的应用项目中测试。
其次,摆脱这一切:
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
closure(name)
做任何你想要纯粹使用GCD的事情。
我不清楚你想做什么; objc_sync_enter
和asyncAfter
的混乱对我来说太神秘了。然而,这些东西一点都不神秘,并且有很好的记录和解释(与你的说法相反)。
从您想要的输出中,看起来您想要排队“线程1”操作并让它在“线程2”操作开始之前从头到尾运行。
sync
而不是async
调用“线程1”操作,因为这意味着您的代码会等待(阻塞),直到操作完成并返回。以下是第一种方式的示例,我认为这是更好的方法:
let queue = DispatchQueue(label:"myqueue") // serial queue
func go() {
for i in 0..<4 {
let name = "Thread \(i)"
queue.async {
for i in 0..<4 {
let str = "\(name) :: \(i)"
print(str)
}
}
}
}
我们致电go()
时的输出:
Thread 0 :: 0
Thread 0 :: 1
Thread 0 :: 2
Thread 0 :: 3
Thread 1 :: 0
Thread 1 :: 1
Thread 1 :: 2
Thread 1 :: 3
Thread 2 :: 0
Thread 2 :: 1
Thread 2 :: 2
Thread 2 :: 3
Thread 3 :: 0
Thread 3 :: 1
Thread 3 :: 2
Thread 3 :: 3
这看起来很像你说的你想要的。