1. ホーム
  2. スクリプト・コラム
  3. ゴラン

囲碁相互排他ロックと読み書き相互排他ロックの実装

2022-02-14 23:20:29

このコードの問題点を見てみましょう。

jdbc.driverClass=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@nantianpaydb.baidupay.com:8002:ntpzn
jdbc.user=cif
jdbc.password=cif
#druid datasource
druid.initialSize=10
druid.minIdle=10
druid.maxIdle=100
druid.maxActive=500
druid.maxWait=30000
druid.timeBetweenEvictionRunsMillis=60000
druid.minEvictableIdleTimeMillis=300000
druid.validationQuery=SELECT 1 from dual
druid.testWhileIdle=true
druid.testOnBorrow=false
druid.testOnReturn=false
druid.poolPreparedStatements=true
druid.maxPoolPreparedStatementPerConnectionSize=20
druid.filters=wall,stat
 

20000ではなく、12135(マシンによって結果が異なる)と出力された理由は以下の通りです。

xの代入は、xの値を取り出す、xの結果を計算する、xに値を代入する、という合計3つのステップに分かれているため、f関数呼び出しにゴルーチン並列を使用しているので、リソース競合の問題があり、代入と計算の間にダーティデータが存在することになるのです。この問題は、相互に排他的なロックを使用することで解決できます。

相互排他ロック

相互排他ロックは、共有リソースへのアクセスを制御する一般的な方法で、一度に1つのゴルーチンしか共有リソースにアクセスできないようにします。ミューテックスは、Go 言語で sync パッケージの Mutex タイプを使用して実装されています。

# cat /proc/sys/kernel/sem

mutually exclusive lockを使用することで、1つのゴルーチンだけが同時にクリティカルゾーンに入り、他のゴルーチンはロックを待ちます。mutually exclusive lockが解除されると、待っているゴルーチンはロックを取得してのみクリティカルゾーンに入り、複数のゴルーチンが同時にロックを待っている場合のウェイクアップポリシーはランダムです。

リード/ライトミュテックスロック

相互排他ロックは完全に排他的なロックですが、現実的には読み込みが多く書き込みが少ないシーンが多く、リソースの変更を伴わない同時読み込みの場合はロックを追加する必要がないので、そのような場合は読み書きロックを使用する方が良いでしょう。読み書きロックは、Go言語ではsyncパッケージのRWMutex型で使用されています。

読み書きロックには、リードロックとライトロックの2種類があります。あるゴルーチンがリードロックを取得すると、他のゴルーチンはリードロック取得中であればロックを取得し続け、ライトロック取得中であれば待ち、あるゴルーチンがライトロックを取得すると、他のゴルーチンはリードロック、ライトロックに関わらず待ちます。

# echo "kernel.sem=250 32000 100 128" >> /etc/sysctl.conf

これは、Goのmutexロックと読み書きmutexロックの実装に関するこの記事の終わりです、より関連するGoのmutexロックと読み書きmutexロックの内容は、スクリプトハウスの以前の記事を検索するか、次の関連記事を閲覧を続けてください、あなたは将来的にもっとスクリプトハウスをサポートしています願っています