5

Why is it imposible to enter critical section without Sleep(1)?

type
  TMyThread = class(TThread)
  public
    procedure Execute; override;
  end;

var
  T: TMyThread;
  c: TRTLCriticalSection;

implementation

procedure TForm1.FormCreate(Sender: TObject);
begin
  InitializeCriticalSection(c);
  T := TMyThread.Create(false);
end;

procedure TMyThread.Execute;
begin
  repeat
    EnterCriticalSection(c);
    Sleep(100);
    LeaveCriticalSection(c);
    sleep(1);  // can't enter from another thread without it
  until false;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  EnterCriticalSection(c);
  Caption := 'entered';
  LeaveCriticalSection(c);
end; 

Can't post this because of too much code so text text text text text. Oh by the way if the section is created by the thread then it is working fine.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 3
    Because the window of opportunity is too narrow. The thread gives up the section, but then immediately reclaims it. – David Heffernan Nov 29 '17 at 10:27
  • Calling `Sleep(1)` doesn't do anything particularly interesting. You probably meant to call `Sleep(0)` instead, as [documented](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686298.aspx). Also, please edit your question with more detail, instead of the useless placeholder text. – IInspectable Nov 29 '17 at 12:47
  • Sleep(0) didn't work in my case. Only Sleep(>=1) does the trick. Anyway J... answered my question. I didn't know that microsoft changed the behaviour of the critical sections since XP – Snus Mumrik Nov 29 '17 at 13:54
  • Microsoft may well have changed the undefined behaviour of the critical sections since XP. If you make assumptions beyond that documented, don't be surprised when you get bitten:( – Martin James Nov 29 '17 at 16:39
  • @MartinJames: This isn't *undefined behavior*. It's an implementation detail. Though well defined in and of itself, writing code that relies on it is brittle, and can break at any time, so I agree with the second part of your comment. – IInspectable Nov 29 '17 at 18:13

1 Answers1

8

There is no guarantee that threads acquire a critical section on a FIFO basis (MSDN). If your current thread always re-acquires the critical section a few uops after releasing it then chances are that any other waiting threads will likely never wake in time to find it available themselves.

If you want better control of lock sequencing there are other synchronization objects you can use. Events or a queue might be suitable but we don't really know what you are trying to achieve.

J...
  • 30,968
  • 6
  • 66
  • 143