这是在Java中使用synchronized的正确方法吗?

时间:2016-07-09 11:48:05

标签: java multithreading

此处显示的for循环在一个线程中运行。在同步块内,线程写入某个文件。有几个不同的文件,因此编写器保存在一个数组中。我想要确保的是,没有两个不同的线程同时写入同一个文件。但是,他们可以写入不同的文件。我在同步块中使用了正确的参数吗?

for(Element e: elements)
{
    int i = getWriterIndex(e)
    writeri = writers(i)
    synchronized(writeri)
    {
        // Write to corresponding segment
        writers(i).write(e)
        recordsWritten(i) += 1
    }
}

2 个答案:

答案 0 :(得分:1)

是的,只要同步块仅访问用作锁的数据结构,您的同步代码将按预期工作。因此,在您的代码中,多个线程无法同时访问 writeri ,因此它是线程安全的。

但是,你必须确保你没有在其他地方访问变量 recordsWritten ,因为那时你将有竞争条件。因此,理想情况下,您也可以锁定该变量(在您访问它的每个位置),或者您可以使用某些Java原语,例如AtomicInteger

答案 1 :(得分:1)

虽然我认为这会有用,但我强烈建议您避免使用synchronized。原因是您最终要严格执行同步策略是很常见的。正如其他人所说,这似乎是队列的完美用例。

如果你不想在大多数场景中使用队列(包括这个),我建议使用锁来保持线程安全(通常是ReentrantReadWriteLock)。您可以找到示例here

在你的情况下,我会为每个编写器创建一个锁,并要求为了使用编写器,当前线程必须持有writelock。 (如果您只是写作,可以使用简单的锁而不是ReentrantReadWriteLock。