通过下面的代码,我有两个类A的实例-a1和a2。并分别在两个实例上调用方法foo()。
在foo()方法中有一个同步块,该块已锁定在调用对象上。由于这是一个实例级锁定,因此这两种方法应同时开始执行,因为它们是从两个单独的实例中调用的。但是,它们是按顺序执行的。
是因为两个实例都从同一个线程主线程调用吗?
代码更改:使类A实现Runnable,将foo()重命名为run(),从main分叉线程t,从主线程调用a1.run(),从线程t调用a2.run()。尽管从两个线程(主线程和线程t)调用了两个A实例a1和a2,但同步块似乎已被锁定。
我的理解是,“ this”是指调用Runnable实例,该实例不同,甚至线程也不同。因此,Thread.sleep不应使其他线程被阻塞。然后,为什么运行的两个调用不是同时发生的?
预期输出(应并行执行)
func spawnShape() {
// 1
var geometry:SCNGeometry
let positions = [
SCNVector3(-2, 1.5, 0), //0
SCNVector3(-2, 1.5, 0), //1
SCNVector3(2, -1.5, 0), //2
SCNVector3(2, 1.5, 0), //3
SCNVector3(-2, 1.5, 0.4), //4
SCNVector3(2, 1.5, 0.4) //5
]
let source = SCNGeometrySource(vertices: positions)
let indices:[CInt] = [
0, 2, 1,
0, 3, 2,
0, 4, 5,
0, 5 ,3,
4, 1, 2,
4, 2, 5
]
let element = SCNGeometryElement(indices: indices, primitiveType:.triangles)
// 4
geometry = SCNGeometry(sources: [source], elements: [element])
let geometryNode = SCNNode(geometry: geometry)
// 5
scnScene.rootNode.addChildNode(geometryNode)
}
}
实际输出(按顺序执行)
main <time> Inside A.run
Thread-0 <time> Inside A.run
Thread-0 <time+4s> Exiting A.run
main <time+5s> Exiting A.run
main <time> Inside A.run
main <time+5s> Exiting A.run
Thread-0 <time+5s> Inside A.run
Thread-0 <time+9s> Exiting A.run
答案 0 :(得分:1)
是因为两个实例都从同一实例被调用 主线程?
是的。调用Thread.sleep()是同步的,除非中断,否则它将在持续时间内阻止当前线程。您直接调用a1.foo(),它将在持续时间内阻止主线程,这是您看到的结果。创建单独的线程并在每个线程中调用foo(),您将看到期望的行为。
答案 1 :(得分:1)
您开始在启动线程之前同步运行a1
,当然您会在主线程上获得a1的输出,因为在a1完成之前,它无法到达线程启动语句。>
尝试在主线程上运行a2
之前先启动运行a1
的线程,看看会得到什么。
您还应该注意,线程调度可能会延迟,并且调用Thread#start
不会立即在单独的线程上开始执行,而是将其排队给系统线程调度程序。您可能还想考虑使用诸如CyclicBarrier
之类的同步设备,以便在运行a2
的线程和运行a1
的主线程之间进行协调,否则您可能 still < / em>会获得完全相同的结果,即使您似乎在a1
之前启动线程来运行a2
。