Multithreading and Critical Sections Use - C++
I'm a little confused as to the proper use of critical sections in multithreaded applications. In my applicat开发者_开发知识库ion there are several objects (some circular buffers and a serial port object) that are shared among threads. Should access of these objects always be placed within critical sections, or only at certain times? I suspect only at certain times because when I attempted to wrap each use with an EnterCriticalSection
/ LeaveCriticalSection
I ran into what seemed to be a deadlock condition. Any insight you may have would be appreciated. Thanks.
If you share a resource across threads, and some of those threads read while others write, then it must be protected always.
It's hard to give any more advice without knowing more about your code, but here are some general points to keep in mind.
1) Critical sections protect resources, not processes.
2) Enter/leave critical sections in the same order across all threads. If thread A enters Foo, then enters Bar, then thread B must enter Foo and Bar in the same order. If you don't, you could create a race.
3) Entering and leaving must be done in opposite order. Example, since you entered Foo then entered Bar, you must leave Bar before leaving Foo. If you don't do this, you could create a deadlock.
4) Keep locks for the shortest time period reasonably possible. If you're done with Foo before you start using Bar, release Foo before grabbing Bar. But you still have to keep the ordering rules in mind from above. In every thread that uses both Foo and Bar, you must acquire and release in the same order:
Enter Foo
Use Foo
Leave Foo
Enter Bar
Use Bar
Leave Bar
5) If you only read 99.9% of the time and write 0.1% of the time, don't try to be clever. You still have to enter the crit sec even when you're only reading. This is because you don't want a write to start when your'e in the middle of a read.
6) Keep the critical sections granular. Each critical section should protect one resource, not multiple resources. If you make the critical sections too "big", you could serialize your application or create a very mysterious set of deadlocks or races.
Use a C++ wrapper around the critical section which supports RAII:
{
CriticalSectionLock lock ( mutex_ );
Do stuff...
}
The constructor for the lock acquires the mutex and the destructor releases the mutex even if an exception is thrown.
Try not to gain more more than one lock at a time, and try to avoid calling functions outside of your class while holding locks; this helps avoid gaining locks in different places, so you tend to get fewer possibilities for deadlocks.
If you must gain more than one lock at the same time, sort the locks by their address and gain them in order. That way multiple processes gain the same locks in the same order without co-ordination.
With an IO port, consider whether you need to lock output at the same time as input - often you have a case where something tries to write, then expects to read, or visa-versa. If you have two locks, then you can get a deadlock if one thread writes then reads, and the other reads then writes. Often having one thread which does the IO and a queue of requests solves that, but that's a bit more complicated than just wrapping calls up with locks, and without much more detail I can't recommend it.
精彩评论