同步方法Java

同步方法Java,java,multithreading,concurrency,synchronization,Java,Multithreading,Concurrency,Synchronization,我有一个关于线程间同步的问题 实际上,我有一个只读取静态变量的方法。一些线程访问此变量,但没有写入,只有读取 我必须声明该方法已同步吗 如果没有为变量设置新值,则不需要同步它们就可以了。答案是明确的否。这不是必需的,而且会浪费时间。在读写模式下访问资源时,同步是将线程排序在一起的问题 如果未修改该值,则将该变量的评估员标记为已同步是无用的 然而,如果变量是对象,则返回BER属性的内部表示可能会造成损害,因为您返回了对该对象的引用 因此,即使是读取,也无法阻止代码稍后更改值 这就是为什么一些bug

我有一个关于线程间同步的问题

实际上,我有一个只读取静态变量的方法。一些线程访问此变量,但没有写入,只有读取


我必须声明该方法已同步吗

如果没有为变量设置新值,则不需要同步它们就可以了。

答案是明确的否。这不是必需的,而且会浪费时间。

在读写模式下访问资源时,同步是将线程排序在一起的问题

如果未修改该值,则将该变量的评估员标记为已同步是无用的

然而,如果变量是对象,则返回BER属性的内部表示可能会造成损害,因为您返回了对该对象的引用

因此,即使是读取,也无法阻止代码稍后更改值

这就是为什么一些bug跟踪工具在返回可变对象的内部引用时会发出警告

有些本质上是不可变的,比如字符串、整数。。。。和所有原语(始终按值传递)

要防止BEN的可变性,您可以做的是在返回变量之前复制该变量(如果该变量是可变类型)

例如,您需要返回myDate字段的值:

private Date myDate;

public Date getMyDate(){
  // returning a copy of the myDate variable
  return (this.mydate==null)?null:new Date(this.mydate.getTime());
}

您不需要使方法
同步
,但是如果您使用来自多个线程的某个变量(静态或非静态),则应该有一个同步机制

  • 如果只初始化变量一次,则只需确保一次即可

    • 如果初始化可以是快速的,那么应该使用一种经过验证的习惯用法,如双重检查锁定(正确编写)或按需初始化
  • 如果期望偶尔写入变量,则应消除数据争用的机会。您应该确保写入的原子性以及这些写入对读者的可见性

    • 执行此操作的一种常见方法是通过
      synchronized
      方法写入,使变量
      易变
      ,如果变量是复杂对象,则确保其字段的安全发布
没有写作,只有阅读

那么就不需要
同步


<>强>但是,你应该考虑制作静态变量<代码>最终< /代码>,正如你已经说过的,它只用于阅读目的。此步骤将保证将来不会出现任何可能的并发危害。

否。没有必要将读取操作声明为同步。这是常数吗?它是如何初始化的?如果线程A从
synchronized(o)
块中更新某个变量
v
,这不足以与读取
v
的其他线程B建立“发生在”关系。以前最常用的建立方法是线程B只从另一个
synchronized(o)
块中读取
v
。@jameslarge您是对的,但我不确定您的观点是否与我的答案有任何关系。在
synchronized
块中写入和通过
volatile
字段读取是一种有效的同步机制,适用于大量以读取为主的用例。看看Brian Goetz在这里称之为“廉价读写锁”的东西:哎呀!我没有读完整的句子:“一种常见的方法是通过同步方法写入,使变量易变,以及……”对不起,不必要地使用“volatile”是不好的做法,因为“volatile”是expensive@penguin这是一个基本正确的说法,但它并没有真正澄清,请更正或联系上述答案或我对@jameslarge的回复,这可能会让读者感到困惑,因为我不建议在不必要的地方使用
volatile