In a multithreading environment you have to take care of synchronization so two threads doesn't clobber the state by simultaneously performing modifications. Otherwise you can have race conditions in your code (for an example see the infamous Therac-25 accident.) You also have to schedule the threads to perform various tasks. You then have to make sure that your synchronization and scheduling doesn't cause a deadlock where multiple threads will wait for each other indefinitely.
Synchronization
Something as simple as increasing a counter requires synchronization:
counter += 1;
Assume this sequence of events:
counter is initialized to 0
- thread A retrieves
counter from memory to cpu (0)
- context switch
- thread B retrieves
counter from memory to cpu (0)
- thread B increases
counter on cpu
- thread B writes back
counter from cpu to memory (1)
- context switch
- thread A increases
counter on cpu
- thread A writes back
counter from cpu to memory (1)
At this point the counter is 1, but both threads did try to increase it. Access to the counter has to be synchronized by some kind of locking mechanism:
lock (myLock) {
counter += 1;
}
Only one thread is allowed to execute the code inside the locked block. Two threads executing this code might result in this sequence of events:
- counter is initialized to 0
- thread A acquires
myLock
- context switch
- thread B tries to acquire
myLock but has to wait
- context switch
- thread
answered 2009-08-24T10:40:53.017