Q re Thread Safe Dictionary and delegates

S

Simon Woods

Hi

I am developing a webservice. I need to authenticate webrequests. I am
using a dictionary to keep track of authenticated users. In order to do
this, prior to adding an entry into the dictionary I need to perform
some DB access to validate the user.

Because it is a webservice, I am slightly concerned about threadsafety,
particularly race conditions which may arise when an authentication has
expired and I need to remove it from the dictionary.

I have found several implementations of threadsafe dictionaries which
use locks to maintain threadsafety, but obviously I need to include the
DB checking within the threadsafety mechanism.

I know I could modify the implementation of the dictionary to include
db access, but I don't think that is the best way, and I would rather
find another way whereby I either inherit the threadsafe dictionary into
another threadsafe container - but then it seems that there'd be 2
levels of locking.

I haven't used delegates that much and was wondering if I could use
delegates to effectively "transactionalise" the db access/adding to
dictionary but I'm not sure if they would give me the threadsafety I am
after.

Appreciate any suggestions, pointers to articles etc.

Many Thx

Simon
 
J

Jeroen Mostert

I am developing a webservice. I need to authenticate webrequests. I am
using a dictionary to keep track of authenticated users. In order to do
this, prior to adding an entry into the dictionary I need to perform
some DB access to validate the user.

Because it is a webservice, I am slightly concerned about threadsafety,
particularly race conditions which may arise when an authentication has
expired and I need to remove it from the dictionary.

I have found several implementations of threadsafe dictionaries which
use locks to maintain threadsafety, but obviously I need to include the
DB checking within the threadsafety mechanism.
What's wrong with

authenticationDetails = performDbAuthentication(credentials);
if (authenticationDetails.Authenticated) {
lock (dictionary) {
if (!dictionary.ContainsKey(userKey)) dictionary.Add(userKey,
authenticationDetails);
}
}

You don't even need to check if all you care about is that the user was
authenticated:

authenticationDetails = performDbAuthentication(credentials);
if (authenticationDetails.Authenticated) {
lock (dictionary) {
dictionary[userKey] = authenticationDetails;
}
}

I do not advocate stuffing the thread-safety mechanisms in the dictionary
itself. This approach only works if you have a small, easily identifiable
set of operations that need to be atomic individually. It doesn't generalize
(as in the example above, where we need two operations to work as a whole).
Use a higher-level class that encapsulates the dictionary but doesn't
require it to be thread-safe.
 
S

Simon Woods

I am developing a webservice. I need to authenticate webrequests. I am
using a dictionary to keep track of authenticated users. In order to do
this, prior to adding an entry into the dictionary I need to perform
some DB access to validate the user.

Because it is a webservice, I am slightly concerned about threadsafety,
particularly race conditions which may arise when an authentication has
expired and I need to remove it from the dictionary.

I have found several implementations of threadsafe dictionaries which
use locks to maintain threadsafety, but obviously I need to include the
DB checking within the threadsafety mechanism.
What's wrong with

authenticationDetails = performDbAuthentication(credentials);
if (authenticationDetails.Authenticated) {
lock (dictionary) {
if (!dictionary.ContainsKey(userKey)) dictionary.Add(userKey,
authenticationDetails);
}
}

You don't even need to check if all you care about is that the user was
authenticated:

authenticationDetails = performDbAuthentication(credentials);
if (authenticationDetails.Authenticated) {
lock (dictionary) {
dictionary[userKey] = authenticationDetails;
}
}

I do not advocate stuffing the thread-safety mechanisms in the
dictionary itself. This approach only works if you have a small, easily
identifiable set of operations that need to be atomic individually. It
doesn't generalize (as in the example above, where we need two
operations to work as a whole). Use a higher-level class that
encapsulates the dictionary but doesn't require it to be thread-safe.

Ok. thanks .. I was obviously overcomplicating it!
 
P

Peter Duniho

Simon said:
[...]
authenticationDetails = performDbAuthentication(credentials);
if (authenticationDetails.Authenticated) {
lock (dictionary) {
dictionary[userKey] = authenticationDetails;
}
}

I do not advocate stuffing the thread-safety mechanisms in the
dictionary itself. This approach only works if you have a small, easily
identifiable set of operations that need to be atomic individually. It
doesn't generalize (as in the example above, where we need two
operations to work as a whole). Use a higher-level class that
encapsulates the dictionary but doesn't require it to be thread-safe.

Ok. thanks .. I was obviously overcomplicating it!

I agree with Jeroen's comments that separating the duties of
synchronization from the dictionary itself is a good idea. As he points
out, it's more extensible to do it that way, allowing you the option of
combining dictionary operations with others that need to happen
atomically with those, without having the dictionary class itself have
to be involved.

That said, I want to comment on a specific aspect of his example: that
is, the use of the dictionary reference itself for locking. IMHO, this
is a bad idea. I always try to use a specific, private object instance
that is used only for locking, never exposed outside the class using it.
This ensures that no other code will attempt to synchronize on the
same object, and thus no other class will have the lock when your own
synchronized code needs to acquire it.

It's not a 100% guarantee against deadlock, but it's a major step in
that direction, and can be a part of an overall guarantee as long as
you're careful with the rest of the implementation (i.e. eliminating
other externalities where it could be possible to be holding that lock
when some outside code attempts to acquire a second lock elsewhere).

Pete
 
S

Simon Woods

authenticationDetails = performDbAuthentication(credentials);
if (authenticationDetails.Authenticated) {
lock (dictionary) {
dictionary[userKey] = authenticationDetails;
That said, I want to comment on a specific aspect of his example: that
is, the use of the dictionary reference itself for locking. IMHO, this
is a bad idea. I always try to use a specific, private object instance
that is used only for locking, never exposed outside the class using it.
This ensures that no other code will attempt to synchronize on the same
object, and thus no other class will have the lock when your own
synchronized code needs to acquire it.

It's not a 100% guarantee against deadlock, but it's a major step in
that direction, and can be a part of an overall guarantee as long as
you're careful with the rest of the implementation (i.e. eliminating
other externalities where it could be possible to be holding that lock
when some outside code attempts to acquire a second lock elsewhere).

Thanks Peter.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top