From: Piranha on
I have a multithreaded application, where all threads need access to
an array of data.
To make it thread safe, I´ve encapsulated all access to that array in
a named mutex, like this:

// global
CreateMutex(0,0,"SomeUniqueText");

DWORD WINAPI SomeThread(LPVOID data)
{

....

HANDLE hMutex = OpenMutex(SYNCHRONIZE,0,"SomeUniqueText");
WaitForSingleObject(hMutex,INFINITE);

// read write array

ReleaseMutex(hMutex);
CloseHandle(hMutex);

....

return 0;

}

This seems to work all fine, but once in a while the program seems to
lag, from a few seconds up to a minute or so.
There could be several other causes for this, I´m just trying to rule
out this one, so the question is:

If one thread holds the mutex and 2 or more other threads try to
access the mutex before the first one releases it, what happens at the
time of release? Does the system keep an order of access, or are the
threads blocking each other in their attempt to capture the mutex?
From: Gunnar on
> I have a multithreaded application, where all threads need access to
> an array of data.
> To make it thread safe, I�ve encapsulated all access to that array in
> a named mutex, like this:

If all threads are part of the same process, a critical section would do the
trick as well, with much less effort. Just create the critical section
instead of the mutex, and then all you have to do is to surround the access
to your data by calls to EnterCriticalSection/LeaveCriticalSection.
The purpose of mutexes is inter-process synchronization - although they
work in your case as well, of course.


> // global
> CreateMutex(0,0,"SomeUniqueText");

Why not store the handle of the mutex globally? How do you close this
handle?

> DWORD WINAPI SomeThread(LPVOID data)
> {
>
> ...
>
> HANDLE hMutex = OpenMutex(SYNCHRONIZE,0,"SomeUniqueText");

You wouldn't need this call then (and the call to CloseHandle when your
thread is done as well).

> If one thread holds the mutex and 2 or more other threads try to
> access the mutex before the first one releases it, what happens at the
> time of release?

The only thing you can be sure of is that one - and only one - thread will
be resumed, but there's no way to tell Windows which one you want to be
resumed.

> Does the system keep an order of access,

No.

> or are the
> threads blocking each other in their attempt to capture the mutex?

No - one thread will be resumed. Period. :)

From: Ulrich Eckhardt on
Piranha wrote:
> I have a multithreaded application, where all threads need access to
> an array of data.
> To make it thread safe, I´ve encapsulated all access to that array in
> a named mutex, like this:
>
> // global
> CreateMutex(0,0,"SomeUniqueText");

This is completely unnecessary for two reasons:
1. Giving it a name makes it system-global, i.e. accessible from other
processes, too. You don't need that probably.
2. There is a "cheap" mutex called CRITICAL_SECTION that allows syncing
threads within a process. This one can't be used with e.g.
WaitFor-Functions, but otherwise it gets the job done.

> DWORD WINAPI SomeThread(LPVOID data)
[...]
> HANDLE hMutex = OpenMutex(SYNCHRONIZE,0,"SomeUniqueText");

This is correct, but way overcomplicated, as explained above. Note that if
you are worried about ownership issues, you can use e.g. DuplicateHandle()
to give each thread its own handle to the mutex.

> WaitForSingleObject(hMutex,INFINITE);

.... EnterCriticalSection(...)

> // read write array

Where do you get the reference to the array from? You should use the same
mechanism to communicate the lock required to be taken before accessing the
array! Using C++ you could even wrap the whole so that the compiler can
guarantee you that no access without the lock held are made, in C you need
to be disciplined yourself.

> This seems to work all fine, but once in a while the program seems to
> lag, from a few seconds up to a minute or so.
> There could be several other causes for this, I´m just trying to rule
> out this one, so the question is:
>
> If one thread holds the mutex and 2 or more other threads try to
> access the mutex before the first one releases it, what happens at the
> time of release? Does the system keep an order of access, or are the
> threads blocking each other in their attempt to capture the mutex?

Unless the threads have a different priority, it's a first-come first-serve
basis.

Uli

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932

From: Piranha on
On 21 Apr., 14:47, Ulrich Eckhardt <eckha...(a)satorlaser.com> wrote:
> Piranha wrote:
> > I have a multithreaded application, where all threads need access to
> > an array of data.
> > To make it thread safe, I´ve encapsulated all access to that array in
> > a named mutex, like this:
>
> > // global
> > CreateMutex(0,0,"SomeUniqueText");
>
> This is completely unnecessary for two reasons:
> 1. Giving it a name makes it system-global, i.e. accessible from other
> processes, too. You don't need that probably.
> 2. There is a "cheap" mutex called CRITICAL_SECTION that allows syncing
> threads within a process. This one can't be used with e.g.
> WaitFor-Functions, but otherwise it gets the job done.
>
>
>
> > DWORD WINAPI SomeThread(LPVOID data)
> [...]
> > HANDLE hMutex = OpenMutex(SYNCHRONIZE,0,"SomeUniqueText");
>
> This is correct, but way overcomplicated, as explained above. Note that if
> you are worried about ownership issues, you can use e.g. DuplicateHandle()
> to give each thread its own handle to the mutex.
>
> > WaitForSingleObject(hMutex,INFINITE);
>
> ... EnterCriticalSection(...)
>
> > // read write array
>
> Where do you get the reference to the array from? You should use the same
> mechanism to communicate the lock required to be taken before accessing the
> array! Using C++ you could even wrap the whole so that the compiler can
> guarantee you that no access without the lock held are made, in C you need
> to be disciplined yourself.
>
> > This seems to work all fine, but once in a while the program seems to
> > lag, from a few seconds up to a minute or so.
> > There could be several other causes for this, I´m just trying to rule
> > out this one, so the question is:
>
> > If one thread holds the mutex and 2 or more other threads try to
> > access the mutex before the first one releases it, what happens at the
> > time of release? Does the system keep an order of access, or are the
> > threads blocking each other in their attempt to capture the mutex?
>
> Unless the threads have a different priority, it's a first-come first-serve
> basis.
>
> Uli
>
> --
> Sator Laser GmbH
> Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932

Thanks for the answer (to Gunnar as well)
I got the point of making things complicated, have to check out the
critical section thing, but for now all I´m concerned about is this
lag, where I´m trying to rule out possible causes.

So let me get that straight .....
It could be done easier, but my solution should work?
No matter how many threads are waiting for the mutex, only one of them
gets the access and the system has no problems that could result in a
lag in case several threads are waiting?

Or in short: I can rule out this one and have to search my lag
elsewhere?
From: Ulrich Eckhardt on
Piranha wrote:
> I got the point of making things complicated, have to check out the
> critical section thing, but for now all I´m concerned about is this
> lag, where I´m trying to rule out possible causes.
>
> So let me get that straight .....
> It could be done easier, but my solution should work?

A definite "maybe", but with a tendency to "works". The problem is that you
show too little code. Also, if your real code also leaves out the error
handling completely, trouble ensues. Another thing to keep in mind is that
this mutex is indeed system-global, so two instances of your app will
interfere with each other.

> No matter how many threads are waiting for the mutex, only one of them
> gets the access and the system has no problems that could result in a
> lag in case several threads are waiting?
>
> Or in short: I can rule out this one and have to search my lag
> elsewhere?

I would look somewhere else for the lag. I would however make doubly sure
that the multithreaded stuff is correct, as this will give you the nastiest
kind of bugs when only it's only almost correct.

Good luck!

Uli

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932