There's no way to get a single sequential series without locking. It doesn't matter what mechanism you're using to assign the next value - a performance counter, a static variable, whatever - when two threads both need the next value at the same time, one has to wait on the other.
The first thing I'd do is write a test program that spawned a large number of threads which each repeatedly called a locking increment function such as the one Daniel Schaffer posted. That will let you find the threshold where your application starts to thrash - where it's spending more time waiting on Monitor.Enter
than doing anything else.
If that turns out to be a problem - and I'd bet that if the volumes you're talking about are real, it will - then you should make each thread maintain its own sequential counter, which you can do by marking the counter field with the ThreadStaticAttribute
. You can then generate unique identifiers off of a combination of the thread's ID and the counter.
This approach won't work if you're not using a thread pool (since the counter dies when the thread it belongs to does). And you probably also want to make the application's startup count part of the compound ID, so that you don't have to write the thread counters to durable storage. (If you didn't do this, when you restarted the server the threads would start generating counters at zero again, and if your application created a thread with the same ID as an earlier instance, you'd get duplicate identifiers.)
This is obviously not trivial to write (or, more importantly, test), so I'd definitely recommend proving that it's necessary first.