Ser*_*nov 28 java multithreading synchronization
我有一个多线程Java代码,其中:
process()并将其对象传递给那里;process() 以某种方式处理对象,这可能导致更改对象状态;我创建了一个这样的方法:
public void process(Foo[] foos) {
for (final Foo foo : foos) {
if (foo.needsProcessing()) {
synchronized (foo) {
foo.process(); // foo's state may be changed here
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,这看起来很合法.然而,的IntelliJ的检查会抱怨局部变量的同步,因为"不同的线程很可能有不同的本地实例"(这是不是适用于我,因为我不是在方法的初始化的Foo).
基本上我想在这里实现的是与方法Foo.process()同步(这不是我的选项,因为Foo是第三方库的一部分).
我习惯了没有黄色标记的代码,所以社区的任何建议都值得赞赏.在本地人做同步真的很糟糕吗?有没有替代方案可以适用于我的情况?
提前致谢!
Ste*_*n C 22
if (foo.needsProcessing()) {
synchronized (foo) {
foo.process(); // foo's state may be changed here
}
}
Run Code Online (Sandbox Code Playgroud)
我认为上面的片段中存在竞争条件,可能导致foo.process()偶尔在同一个对象上被调用两次.它应该是:
synchronized (foo) {
if (foo.needsProcessing()) {
foo.process(); // foo's state may be changed here
}
}
Run Code Online (Sandbox Code Playgroud)
在本地人同步这真的很糟糕吗?
在本地人本身同步也不错.真正的问题是:
是否不同的线程正在同步正确的对象以实现正确的同步,以及
是否有其他东西可能通过同步这些对象导致问题.
Stephen C的答案有问题,他毫无意义地输入了许多同步锁,奇怪的是,格式化它的更好方法是:
public void process(Foo[] foos) {
for (final Foo foo : foos) {
if (foo.needsProcessing()) {
synchronized (foo) {
if (foo.needsProcessing()) {
foo.process(); // foo's state may be changed here
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
获取同步锁有时可能需要一段时间,并且如果保持同步,则可能会更改某些内容。可能是那段时间改变了foo的需求处理状态。
如果不需要处理对象,则不想等待锁定。而且,获得锁后,可能仍不需要处理。因此,即使它看起来很愚蠢,并且新手程序员可能会倾向于删除其中一项检查,但只要foo.needsProcessing()函数的功能可以忽略不计,这实际上就是执行此检查的合理方法。
让我们回到主要问题,当您要基于数组中的本地值进行同步时,这是因为时间很关键。在这种情况下,您要做的最后一件事是锁定数组中的每个项目或将数据处理两次。仅当您有几个线程执行大量工作并且很少需要触摸相同的数据但可能很好时,才可以同步本地对象。
仅当且仅当处理需要处理的foo会导致并发错误时,此操作才会起作用。当您只想基于数组中的精确对象进行同步时,基本上就需要双门语法。这样可以防止对foo进行双重处理并锁定不需要处理的任何foo。
您只有在非常重要的时候才阻塞线程,甚至仅在需要时才进入锁,这种情况非常少见,并且仅在不阻塞会导致并发错误的那一刻才阻塞线程。