getlock_ex.py
排他ロックを獲得するプログラムです。
排他ロック獲得後5秒sleepして起き上がり、ロックを解放して終了します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/usr/bin/python # coding: utf-8 import fcntl, time def main(): lockfp = file("res.lock", "r") fcntl.flock(lockfp.fileno(), fcntl.LOCK_EX) print "get lock_ex (fileno: %d)!" % lockfp.fileno() print "go sleep 5 (sec)..." time.sleep(5) print "awake!!!" fcntl.flock(lockfp.fileno(), fcntl.LOCK_UN) print "unlock lock_ex (fileno: %d)!" % lockfp.fileno() lockfp.close() if ( __name__ == "__main__" ): main() |
getlock_sh.py
共有ロックを獲得するプログラムです。
共有ロック獲得後5秒sleepして起き上がり、ロックを解放して終了します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/usr/bin/python # coding: utf-8 import fcntl, time def main(): lockfp = file("res.lock", "r") fcntl.flock(lockfp.fileno(), fcntl.LOCK_SH) print "get lock_sh (fileno: %d)!" % lockfp.fileno() print "go sleep 5 (sec)..." time.sleep(5) print "awake!!!" fcntl.flock(lockfp.fileno(), fcntl.LOCK_UN) print "unlock lock_sh (fileno: %d)!" % lockfp.fileno() lockfp.close() if ( __name__ == "__main__" ): main() |
上記のプログラム2つコンソールを開いて、同時に実行すると分かるのですが、 まずfileno()が返す整数値が異なっていても、同じファイルロック資源をキチンと 見に行って、ロックする・しないを判断してくれているということです。
プロセスごとに異なるので恐らくファイルディスクリプタに関係する番号なのでしょう。
ファイルディスクリプタは、プロセスごとに付与される情報で、そこにどのファイルをオープンしているのかや、 そのファイルのstat情報などを保存しています。
でも、以下のようにgetlock_sh.pyを書き換えると、不思議なことが起きます。
getlock_sh.py自信が解放したはずのロックが解放できておらず、2回目のロックが実行できないのです。
従って、getlock_sh.pyは永眠してしまいます。。。
getlock_sh2.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #!/usr/bin/python # coding: utf-8 import fcntl, time def main(): lockfp2 = file("res.lock", "r") lockfp = file("res.lock", "r") fcntl.flock(lockfp.fileno(), fcntl.LOCK_SH) print "get lock_sh (fileno: %d)!" % lockfp.fileno() fcntl.flock(lockfp2.fileno(), fcntl.LOCK_UN) # ★ print "unlock_sh (fileno: %d)!" % lockfp.fileno() fcntl.flock(lockfp2.fileno(), fcntl.LOCK_EX) print "get lock_ex (fileno: %d)!" % lockfp2.fileno() print "go sleep 5 (sec)..." time.sleep(5) print "awake!!!" fcntl.flock(lockfp2.fileno(), fcntl.LOCK_UN) # ★ fcntl.flock(lockfp2.fileno(), fcntl.LOCK_SH) fcntl.flock(lockfp.fileno(), fcntl.LOCK_UN) # ★ lockfp.close() if ( __name__ == "__main__" ): main() |
上記★部分をご覧下さい。
従って次の排他ロック(LOCK_EX)が共有ロックを獲得しているままなので、永遠に獲得できず、
sleepしたまま起き上がってこれないのです。
よって正しくは、上記赤い行のロック取得・解放をlockfpに対して行えばいいのです。