在 java 中使用 sychronized 关键字安全访问成员变量

Safe access to member variables with sychronized keyword in java

当多个线程可以访问一个成员变量时,我总是使用 synchronized 来确保访问安全。

我在访问成员变量的方法中使用了它

public synchronized void foo()
{
  //do something with the member variable
}

或者对成员的每次访问都被 synchronized

包围
synchronized(member)
{
  //do something with the member here
}

我从来没有在多线程应用程序中使用任何其他机制(如信号量和类似机制)来安全访问成员变量,我想知道我是否忽略了什么并且有一个重要的理由为什么我不应该那样做?我使用 synchronized 因为它使用起来非常快,因为我不必创建任何其他对象,如信号量。

存在其他结构来解决某些问题。他们可以

  • 提高性能
  • 避免死锁
  • 启用更高级别的并发抽象,否则将需要非常粗粒度的锁定(当然你也可以称之为 "improve performance")

提高性能的一个简单示例是读写锁,其中数据结构可以安全地供多个线程使用,只要它们只从中读取即可。只有写入者必须获得非共享锁。

写时复制/不可变数据结构/快照可以允许应用程序的一部分处理一些稍微过时的数据集,例如用于报告,没有任何锁定,因此不会阻碍应用程序其他部分的进展。

同步方法调用其他也使用锁的代码的足够复杂的代码最终可能会导致代码路径中的锁不是以相同的顺序获取,这就是死锁的根源。乐观方案(try-lock 或 read-modify-conditional-update-or-retry)可能能够通过错误路径更优雅地处理这种情况,该错误路径可以通知不同的层它必须重试。