16.2 同時に動作するスレッドを1つに制限する

Javaにはsynchronizedというキーワードがあり、これで宣言されたブロックやメソッド内では、同時に1つのスレッドのみが動作します。次のコードは銀行口座を扱うJavaのクラスです。複数のスレッドからのアクセスによるデータ不整合を防ぐために、このキーワードはとても重要なものでした。

// Javaの同期プリミティブ
public class Account {
  private int balance = 0;
  public synchronized int getBalance() {
    return balance;
  }

  public synchronized void transfer(int amount) {
    balance += amount;
  }
}

Goに syncronized のようなキーワードはありませんが、syncパッケージを使うことで、これと同等のことが実現できます。ただしJavaとは違い、低レベルの並列処理プリミティブ、ロックを直接扱う必要があります。

Goのロックにはsync.Mutexsync.RWMutexの2種類があります。前者は単純なロックで、Lock()された後に、誰かがUnlock()するまでは、次のLock()呼び出しをブロックします。後者は少し複雑で、読み込み専用のロックがあります。読み込みであれば値が変化することはないため、読み込み用にロックするメソッド(RLock())は何度でも呼び出せます。値の変更時にはLock()を呼びます。これは他のロックとは排他的に動作するため、他のRLock()Lock()は、変更が完了するまでブロックします。これにより、安全な読み書きが行えます。Go ...