How to use synchronized in Scala?
我有以下代码:
要求ctr值只能使用一次。在我的例子中,EDOCX1的相同值(0)正在被重用。我的理论是,发生这种情况是因为Foo.bar在不同的线程中被同时调用(这是我能得出的唯一结论)。我有以下修改过的代码作为修复。
1 2 3 4 5 6 7 8 9 10 11
| object Foo {
private var ctr = 0L
def getCtr = synchronized {
ctr = ctr + 1
ctr
}
def bar = {
val currCtr = getCtr
// do something with currCtr
}
} |
我找不到在scala中使用synchronized方法的好指南。有人能告诉我上面的代码是否能解决我的问题吗?
编辑:根据下面的评论,我认为AtomicLong是我的最佳解决方案:
1 2 3
| import java. util. concurrent. atomic. AtomicLong
private val ctr = new AtomicLong
def getCtr = ctr. incrementAndGet |
- 你已经看过twitter.github.io/scala_school/concurrency.html了吗?你也可以使用原子长。
- 我会回避这个问题,使用AtomicInteger。这些是为并发计数器而设计的。
- + 1。我理解对更高级别并发性(期货、参与者等)的强调,但遗憾的是,最终的scala书籍甚至没有提到obj.synchronized语法。
如果你不想要一个AtomicInteger,这里是如何使用synchronized。
1 2 3 4 5 6 7 8 9 10 11
| object Foo {
private var ctr = 0L
def getCtr = this. synchronized {
ctr = ctr + 1
ctr
}
def bar = {
val currCtr = getCtr
// do something with currCtr
}
} |
您需要在某些对象上进行同步。在本例中,您当前的对象是this。
它相当于Java的
Scala没有EDCOX1和1种方法作为Java,只是块。
编辑
回答下面评论中的问题:synchronized可用作AnyRef类的一种方法:
https://www.scala-lang.org/api/current/scala/anyref.html
1
| final def synchronized [T0 ](arg0 : ? T0 ): T0 |
所以您调用对象的方法,就像调用toString和this.toString一样。
- 如果我跳过this,会发生什么?这段代码的确是编译好的,而且似乎运行正常。
- @Jus12我编辑了我的答案
- 注意,与toString不同,它实际上不是AnyRef上的一个方法,编译器只是假装它是。
- 在object中,this.synchronized {...}与synchronized {...}相同吗?
- @?Ukasz二者中,AtomicLong或synchronized哪一个是首选的?
- 是的,它和它作为一种方法的工作原理是一样的。如果你有A { def a = 3; def b = a; def c = this.a }类b类和c类,你也会这样做。一般来说,最好不要使用像synchronized、wait、notify这样的东西,因为它们水平低,容易出错。AtomicLong也更快。您可以阅读以下关于同步与原子的内容:stackoverflow.com/questions/9749746/…
- "它实际上不是anyref上的一个方法,编译器只是假装它是。"这几乎就是scala的故事。