views:

120

answers:

6

I have multiple threads starting at the roughly the same time --- all executing the same code path. Each thread needs to write records to a table in a database. If the table doesn't exist it should be created. Obviously two or more threads could see the table as missing, and try to create it.

What is the preferred approach to ensure that this particular block of code is executed only once by only one thread.

While I'm writing in C# on .NET 2.0, I assume that the approach would be framework/language neutral.

+1  A: 

This is what Semaphores are for.

Joshua
Seems like a Monitor should suffice for his scenario?
Abhijeet Patel
He asked "not language specific" or I would have pointed him to monitor or mutex. Semaphore is available in almost all multithreaded languages.
Joshua
To be precise, he said "I assume that the approach would be framework/language neutral." which is a statement of opinion rather than a request.
Adam Robinson
+2  A: 

Something like this should work...

private object lockObject = new object();

private void CreateTableIfNotPresent()
{
    lock(lockObject)
    {
        // check for table presence and create it if necessary, 
        // all inside this block
    }
}

Have your threads call call the CreateTableIfNotPresent function. The lock block will ensure that no thread will be able to execute the code inside of the block concurrently, so no threads will be able to view the table as not present while another is creating it.

Adam Robinson
lockObject should be public static so it can be shared across threads.
ebpower
@ebpower: Depending on how the threads are constructed you could certainly be correct, but not necessarily. I'd leave that decision up to the implementer.
Adam Robinson
Not a panacea. locks are a solution but often a sign of a more fundamental problem i.e what do I lock? Do I lock the variable, the class and then what impact does that lock have? Just because C# has a lock keyword doesn't mean I can use it with impunity to solve all my concurrency issues
zebrabox
@zebrabox: That seems like so much hyperbole. Can you use a `lock` to solve all of your concurrency issues? Obviously not, or items like plural semaphores and `Mutex` classes wouldn't need to exist. For something of this nature, `lock` seems perfectly suited. There is a single point of contact (the `CreateTableIfNotPresent` function), so there isn't even any worry about having to ensure that you `lock` the right object elsewhere. To say that `locks` are a sign of a fundamental problem is silly.
Adam Robinson
A: 

You may not even need to bother with locks since your database shouldn't let you create multiple tables with the same name. Why not just catch the appropriate exceptions and if two threads try to create the same table, one wins and continues on, while the other recovers and continues on.

ebpower
+1  A: 

This is a classical application for either a Mutex or a Semaphore

A mutex ensures that a specific piece of code (or several pieces of code) can only be run by a single thread at a time. You could be clever and use a different mutex for each table, or simply constrain the whole initialisation block to one thread at a time.

A semaphore (or set of semaphores) could perform exactly the same function.

Most lock implementations will use a mutex internally, so look at what lock code is already available in the language or libraries you are using.

@ebpower has it right that in certain applications, you would actually be more efficient to catch an exception caused by an attempt to create the same table multiple times, though this may not be the case in your example.

However there are many other ways of proceeding. For example, you could use a single-threaded ExecutorService (sorry, I could only find a Java reference) that has responsibility for creating any tables that your worker threads discover are missing. If it gets two requests for the same table, it simply ignores the later ones.

A variant on a Memoizer (remembering table references, creating them first if necessary) would also work under the circumstances. The book Java Concurrency In Practice walks through the implementation of a nice Memoizer class, but this would be pretty simple to port to any other language with effective concurrency building blocks.

Bill Michell
Mutex and Semaphore are typically used for cross-process interaction. Both are reasonably heavyweight solutions for the problem posed and IMO using a sledgehammer to crack a nut
zebrabox
A: 
Chansik Im
A: 

I'd use a thread sync object such as ManualResetEvent though it sounds to me like you're willing a race condition which may mean you have a design problem
Some posts have suggested Mutexes - this is an overkill unless your threads are running on different processes.
Others have suggested using locks - this is fine but locking can lead to over-pessimistic locks on data which can negate the benefit of using threads in the first place. A more fundamental question is why are you doing it this way at all? What benefit does threading bring to the problem domain? Does concurrency solve your problem?

zebrabox