Nihongo (Japanese)

File#flock

This script is written to check the function of flock. The same file is accessed by several threads. In each thread, a number is read from the file, incremented, and written to the file. If flock works well, the number written to the file finally should be equal to the total number of iterations.

The procedure of file access is as follows;

  1. Open the file for reading and writing (r+)
  2. Lock the file (exclusive lock)
  3. Read number from the file
  4. Increment the number
  5. Set the file position indicator to the beginning of the file
  6. Write the number to the file
  7. Close the file (explicitly unlocked)

Below is the script for checking the function of flock.

#!/usr/local/bin/ruby
# flock00.rb : test for flock
# 1999/12/20 11:28:15 msato
# $Id: flock-en.uhtml,v 1.4 2000-01-04 18:44:49+09 msato Exp $

require 'thread'

$fname = 'count.dat'
$number_of_threads = 5
$number_of_iteration = 3000
$indent = "\t"

def count(num)
  $number_of_iteration.times do
    open($fname, "r+") do |f|
      f.flock(File::LOCK_EX) # <==== lock
      count = f.gets.to_i + 1
      f.rewind
      f.print count
#      f.flock(File::LOCK_UN) # <==== unlock
      $stderr.print $indent * num, count, "\n"
    end
  end
end

begin
  open($fname, "w") do |f|
    f.print "0"
  end
rescue
  $stderr.print "Cannot open #{fname}\n"
  exit 1
end

th = []
0.upto ($number_of_threads - 1) do |num|
  th[num] = Thread.start { count(num) }
end

0.upto ($number_of_threads - 1) do |num|
 th[num].value
end

print "Count = #{$number_of_threads * $number_of_iteration}\n"
File::delete($fname)

The operation of the file is carried out in count function. Run the script with changing f.flock(File::LOCK_EX) or f.flock(File::LOCK_UN). The results of my tests are as follows;

In this test, it was OK to unlock the file explicitly before closing. However, I've heard the data remained in the buffer result in something wrong when unlocking explicitly before closing.

In the script above, Thread#value is used to suspend the main thread until each thread terminates. But usually, Thread#join is used for this purpose. I haven't noticed Thread#join during programming :-)



[Rabbit Mark] Feel free to mail me

sato.mshr@gmail.com