This needs more investigation before calling it a bug. Memory depletion can be a leak, or it can be due to usage pattern pathology, like checkerboarding.
I'm not familiar with the C++ locking interface, so I don't know the expected lifecycle of the structures involved - perhaps there's some kind of "Free" operation? What happens if you remove the F_UNLCK? Can you keep bouncing between F_RDLCK and F_WRLCK forever? Is there a null lock mode? (ie the lock still exists, but it doesn't block any other lock mode).
Try adding calls to LIB$STAT_VM to see if there's a pattern of depletion. Try sampling all statistics at the bottom of each loop. Output a timestamp, and a comma separated list of statistics, including loop counters for both loops (i and j). Give it a T4 header, and you can examine the timeline of VM usage.
If you want finer detail, use FAKE_RTL to trace all calls into VM routines. This will tell you if there's a genuine leak, or some VM usage pathology.
A crucible of informative mistakes