12.07.2015 Views

Accelerated

Accelerated

Accelerated

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

CHAPTER 12 ■ THREADING IN C# 345an item to be queued. When SubmitWorkItem is called, an item is pushed into the queue and it callsMonitor.Pulse to release one of the worker threads. Naturally, access to the queue must be synchronized.In this case, the reference type used to sync access is the queue itself. Additionally, the workerthreads must not wait forever, because they need to wake up periodically and check a flag to see ifthey should shut down gracefully. Optionally, you could simply turn the worker threads into backgroundthreads by setting the IsBackground property inside the Shutdown method. However, in thatcase, the worker threads may be shut down before they’re finished processing their work. Dependingon your situation, that may or may not be favorable. Notice that I chose to use the Interlockedmethods to manage the stop flag used to indicate that the worker threads should exit.■Note Another useful technique for telling threads to shut down is to create a special type of work item that tellsa thread to shut down. The trick is that you need to make sure you push as many of these special work items ontothe queue as there are threads in the pool.Locking ObjectsThe .NET Framework offers several high-level locking objects that you can use to synchronizeaccess to data from multiple threads. I dedicated the previous section entirely to one type of lock:the Monitor. However, the Monitor class doesn’t implement a kernel lock object; rather, it providesaccess to the sync lock of every .NET object instance. Previously in this chapter, I also covered theprimitive Interlocked class methods that you can use to implement spin locks. One reason spinlocks are considered so primitive is that they are not reentrant and thus don’t allow you to acquirethe same lock multiple times. Other higher-level locking objects typically do allow that, as long asyou match the number of lock operations with release operations. In this section, I want to coversome useful locking objects that the .NET Framework provides.No matter what type of locking object you use, you should always strive to write code thatkeeps the lock for the least time possible. For example, if you acquire a lock to access some datawithin a method that could take quite a bit of time to process that data, acquire the lock only longenough to make a copy of the data on the local stack, and then release the lock as soon as possible.By using this technique, you will ensure that other threads in your system don’t block for inordinateamounts of time to access the same data.ReaderWriterLockWhen synchronizing access to shared data between threads, you’ll often find yourself in a positionwhere you have several threads reading, or consuming, the data, while only one thread writes, orproduces, the data. Obviously, all threads must acquire a lock before they touch the data to preventthe race condition in which one thread writes to the data while another is in the middle of readingit, thus potentially producing garbage for the reader. However, it sure seems inefficient for multiplethreads that are merely going to read the data rather than modify it to be locked out from eachother. There is no reason why they should not be able to all read the data concurrently without havingto worry about stepping on each other’s toes.The ReaderWriterLock elegantly avoids this inefficiency. In a nutshell, it allows multiple readersto access the data concurrently, but as soon as one thread needs to write the data, everyone exceptthe writer must get their hands off. ReaderWriterLock manages this feat by using two internalqueues. One queue is for waiting readers, and the other is for waiting writers. Figure 12-2 shows ahigh-level block diagram of what the inside of a ReaderWriterLock looks like. In this scenario, fourthreads are running in the system, and currently, none of the threads are attempting to access thedata in the lock.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!