JAVA读、写、单独同步

JAVA读、写、单独同步,java,multithreading,synchronization,thread-safety,Java,Multithreading,Synchronization,Thread Safety,我正在学习多线程,我有一个小问题。 当我在线程之间共享某个变量(ArrayList,或类似double、float的其他变量)时,它是否应该在读/写时由同一个对象进行LCocked?我的意思是,当一个线程设置变量值时,另一个线程可以同时读取而不会出现任何问题吗?或者它应该被同一个对象锁定,并强制线程等待读取,直到它被另一个线程更改为止?所有对共享状态的访问必须由同一个锁保护,包括读取和写入。读操作必须等待写操作释放锁 作为一种特殊情况,如果您在同步块中所做的所有操作都是一次读或写操作,那么您可以

我正在学习多线程,我有一个小问题。
当我在线程之间共享某个变量(ArrayList,或类似double、float的其他变量)时,它是否应该在读/写时由同一个对象进行LCocked?我的意思是,当一个线程设置变量值时,另一个线程可以同时读取而不会出现任何问题吗?或者它应该被同一个对象锁定,并强制线程等待读取,直到它被另一个线程更改为止?

所有对共享状态的访问必须由同一个锁保护,包括读取和写入。读操作必须等待写操作释放锁

作为一种特殊情况,如果您在同步块中所做的所有操作都是一次读或写操作,那么您可以省去同步块,并将变量标记为volatile。

简短:这取决于具体情况

更长: 对于每个不同的场景,都有许多“正确答案”。(这让编程变得有趣)

  • 要读取的值是否必须是“最新的”
  • 要写入的值是否已告知所有读者
  • 如果两个线程写入,我应该注意任何争用条件吗
  • 如果读取旧的/以前的值,是否会有任何问题
  • 正确的行为是什么
  • 它真的需要它是正确的吗?(是的,有时你不喜欢好的)
tl;博士

例如,并非所有线程编程都需要“始终正确”

  • 有时您需要权衡正确性和性能(例如日志或进度计数器)
  • 有时,阅读旧的价值观是很好的
  • 有时您需要最终更正(例如,在map reduce中,在所有操作完成之前,没有人或同步的操作是正确的)
  • 在某些情况下,每时每刻都必须正确(例如,您的银行账户余额)
  • 在写一次,只读这没关系
  • 有时,在复杂的情况下分组处理线程
  • 有时许多小型独立锁运行得更快,但有时扁平全局锁运行得更快
  • 还有许多其他可能的情况

这里是我的建议:如果你正在学习,你应该思考“为什么我需要锁?”和“为什么锁在不同的情况下会有帮助?”(不仅仅是教科书中给出的示例),“如果失败会发生什么,或者如果锁丢失会发生什么?”

如果所有线程都在读取,你不需要同步

如果一个或多个线程正在读取,而一个或多个线程正在写入,则需要以某种方式进行同步。如果集合较小,则可以使用
同步
。您可以围绕对集合的访问添加
synchronized
块、
synchronized
访问集合的方法或使用并发线程安全集合(例如,Vector)

如果您有一个大型集合,并且希望允许共享读取但独占写入,则需要使用
ReadWriteLock
。请参见此处,了解JavaDoc和您想要的示例的确切描述:


请注意,这个问题非常常见,在这个网站上有很多类似的例子。

ArrayList是不同步的。因此,如果有多个线程对其进行写入,就会出现问题。此外,每个线程都不能保证最新的值。您可以检查集合的线程安全版本,如ConcurrentSet、ConcurrentMap或CopyOnWriteArrayList。我建议您阅读以下内容:我相信您即将提出的许多问题也会在这里得到解答。