Suppose I have a collection of items which is read and written accross a multithreaded application. When it comes to apply an algorithm over some items I thing of different ways to acquire a lock.
By locking during the entire operation:
lock(collection)
{
for each thing in things
{
get the item from collection that matches thing
do stuff with item
}
}
By locking on demand:
for each thing in things
{
lock(collection)
{
get the it开发者_开发百科em from collection that matches thing
}
do stuff with item
}
Or by locking on demand to get a thread safe collection of items to process later, thus having collection locked for a smaller amount of time:
Items items
for each thing in things
{
lock(collection)
{
get the item from collection that matches thing
}
items.Add(item)
}
for each item in items
{
do stuff with item
}
I know it may eventually depend on the actual algorithm applied to each item, but what would you do? I am using C++, but I am pretty sure it's irrelevant.
Take a look at the Double Check lock pattern which involves separate field for the collection/field under the lock.
Also it worth to take a look at the Readers-writer lock technique which allows reading whilst an other thread updating a collection
EDIT: As David Heffernan mentioned take a look at the The "Double-Checked Locking is Broken" Declaration discussion
In a multi-threaded setting, with thread reading and writing, your first and second examples have different meaning. Your third example could have yet another meaning if "do something with item" interacts with other threads.
You need to decide what you want the code to do before deciding how to do it.
Lock acquisition and release are expensive. I would lock over the collection rather than each individual element in a loop. It makes sense if the entire operation needs to be atomic.
精彩评论