You are having a scoping issue. Because you are using lexically-scoped indirect file handles (
my $self) instead of either a global or bareword, your file handle is going out of scope when the subroutine returns. When it goes out of scope, Perl cleans it up by releasing the flock and closing the file. A quick fix for what you posted is to move your sleep operation into your subroutine. Given that probably defeats your ultimate goal, however, might I suggest returning the file handle and holding onto it in the main script, a la:
#! /usr/bin/perl
use strict;
use warnings;
use Fcntl qw( :flock );
print "Script $0 is running now.\n";
my $lock = Check_Race_Condition();
sleep( 100 );
print "End.\n";
sub Check_Race_Condition {
open( my $self, '<', $0 )
or die( "Another $0 is already running.\n");
flock( $self, LOCK_EX | LOCK_NB )
or die( "Another $0 is already running.\n");
return $self;
}