Solving The Dining Philosophers Problem With Asynchronous AgentsThis article is based on a prerelease version of Visual C++ 2010. All information is subject to change.Enabling C++ developers to write highly concurrent applications is a major focus of Visual Studio 2010. The beta release includes the Concurrency Runtime, parallel libraries, and development tools aimed at addressing several common problems preventing developers from unlocking the performance potential inherent to multicore hardware. Notably, this includes ensuring that developers can identify and take advantage of opportunities for concurrency in their code, productively manage shared state and its side effects, and not having to worry about building low-overhead concurrency infrastructure that is scalable at run time on a variety of hardware.In this article, I’m going to demonstrate how to use the new Asynchronous Agents Library included as part of Visual C++ 2010 to manage the difficulties that can arise with shared state. To show you how this works, I will walk through an implementation of a classic concurrency problem: Djikstra’s Dining Philosophers. You’ll see how the actor-based programming construct of an agent in combination with asynchronous message-passing APIs can be used to provide a correct and easy to understand solution to this problem that doesn’t rely directly on threading or synchronization primitives.The Dining PhilosophersFor those who aren’t familiar with it, the Dining Philosophers problem is intended to illustrate the complexities of managing shared state in a multithreaded environment. Here’s the problem:At a round table sit five philosophers who alternate between thinking and eating from a large bowl of rice at random intervals. Unfortunately for the philosophers, there are only five chopsticks at the table (see Figure 1), and before the philosophers can begin eating, they must acquire a pair of chopsticks. Since the chopsticks are shared between the philosophers, access to the chopsticks must be protected, but if care isn’t taken, concurrency problems arise. Most notably, starvation (pun intended) via deadlock can occur: if each philosopher picks up a chopstick as soon as it is available and waits indefinitely for the other, eventually they will all end up holding only one chopstick with no chance of acquiring another.
Figure 1 The Philosophers and ChopsticksThe Dining Philosophers problem is typically represented in code by a thread for each philosopher and some form of shared state used to represent each of the chopsticks. Straightforward solutions to this problem often involve introducing a waiter entity to coordinate access to the chopsticks, introducing lock ordering heuristics, and manually working with threading APIs, critical sections, semaphores, or monitors to manage the state. Most developers will agree that building correct, nontrivial locking is considered challenging and fragile at best. As a result, most implementations of the Dining Philosophers problem tend to have implementation details leaked into them. For example, the Philosophers may be aware of the synchronization primitives or of their neighbors’ chopsticks. This becomes particularly problematic if you want to generalize the problem to an arbitrary number of philosophers or refocus an implementation on the problem domain—such as what each philosopher does—rather than focusing on the synchronization and threading primitives.An Actor-Based ApproachLet’s walk through a design that is built on top of the Asynchronous Agents Library. Dining Philosophers really only has two moderately difficult sections: creating a thread for each philosopher to run in and coordinating the philosophers’ access to the chopsticks. The Asynchronous Agents Library provides an actor-based programming model and asynchronous message passing APIs, and you’ll need both of these in the implementation. In the Asynchronous Agents Library, the agent class models an actor pattern and provides an asynchronous run method. I use an agent for each philosopher and take advantage of the run method to fulfill the requirement of each philosopher running in its own thread. The second portion of a correct solution involves managing concurrent access to the chopsticks and, in contrast to traditional solutions using semaphores or locks, I’ll use the message passing APIs in the Asynchronous Agents Library to move the chopsticks between the philosophers’ hands and the table. As each philosopher transitions between thinking and eating, he picks up the chopsticks and returns them to the table by sending messages. You’ll see that in addition to providing some abstraction on top of threads and shared state, this will also allow the implementation to stay more focused on the domain of the problem than other solutions enable. A Solution In Five ClassesThe basic design is going to use five types:A Chopstick class that is relatively self explanatory.A ChopstickProvider class that will be used to hold the chopsticks on the table and provide them to the philosophers.A Philosopher class that is responsible for thinking and eating and is aware only of its two ChopstickProviders.A PhilospherState enum that can be thinking or eating. A Table class that contains a set of Philosophers and a set of Chopsticks. Table is responsible for setting the table by placing a single Chopstick in a ChopstickProvider between each Philosopher. Figure 2 shows the relationships between the classes.
Figure 2 Classes Used In The Dining Philosophers SolutionLet’s start with the simplest class: Chopstick. The purpose of the Chopstick is to simply exist as a chopstick and be able to identify itself. As a result, the implementation is a simple class that has an identifier member variable, a constructor that initializes the identifier, and a method to return the identifier. class Chopstick{ const std::string m_Id;public: Chopstick(std::string && Id):m_Id(Id){}; const std::string GetID() { return m_Id; };};It’s important to note that the identifier field m_Id is a const member variable. I don’t want the chopstick to have any state on its own that can get changed accidentally by another thread. Also notice that the constructor is using an r-value reference in its parameter list (the &&). This is a new language construct in Visual Studio 2010 that is part of the draft C++0x standard. An r-value reference here allows the compiler to avoid a copy constructor call and move Id into m_Id within the Chopstick instance if Id is a temporary variable or r-value. Message Blocks And MessagesChopstickProvider is also straightforward. It can be thought of as a storage buffer whose purpose is to accept Chopsticks when they are sent to it and to provide Chopsticks to a Philosopher upon request. Here’s the first place where I use the agent APIs. I use what’s known as a message block for the ChopstickProvider. A message block is defined as a class that is able to send and receive messages. More specifically, if you’re able to send a message to message block, the block is referred to as a target and, if you’re able to receive a message from a message block, it’s referred to as a source. In this example, I’ll need the ChopstickProvider to be both a source and a target because the Philosophers will be both receiving chopsticks from the ChopstickProviders when the Philosophers are hungry and sending them back to the ChopstickProviders when the Philosophers are ready to think again. Here’s an example of putting them to work://create a chopstickChopstick chopstick(“chopstick one”);//create a ChopstickProvider to store the chopstickChopstickProvider chopstickBuffer;//put the chopstick in the chopstick holderConcurrency::send(chopstickBuffer, &chopstick);//request a chopstick from the chopstick bufferChopstick* result = Concurrency::receive(chopstickBuffer);You can see that, after declaring a chopstick and a chopstickBuffer (an instance of the still undefined ChopstickProvider), Concurrency::send is used to place the address of chopstick into the ChopstickBuffer and Concurrency::receive returns a pointer to a Chopstick from the chopstickBuffer. Concurrency::send is a template method that synchronously places a message in a message block. Concurrency::receive is a template method that returns a message from a message block. Concurrency::receive blocks until a message is available in the message block. The Asynchronous Agents Library also provides Concurrency::asend and Concurrency::try_receive. Concurrency::asend asynchronously spawns a task to send the message without waiting for acknowledgement of receipt. Concurrency::try_receive is a non-blocking call that will acquire a message if one is available.Now let’s actually define the ChopstickProvider. Remember I said it was straightforward? It’s a typedef:typedef Concurrency::unbounded_buffer
Rick Molloy is a Program Manager on the Parallel Computing Platform team at Microsoft.
Top 10 Articles,
Silverlight Datagrid Select Update Delete Insert Asp.Net C#
Differences Similarities Benefits Between Typed Datasets and Untyped Datasets asp.net c#
Linq to Sql Introduction Entities Ado.Net C# SqlClasses Attributes Linq Mapping
Linq Programming/How Linq Works?/Linq Implementation In Asp.Net C# Ado.Net
Performing Developing Using Investigating Asp.Net 2.0 Ajax Application Development Asp.Net C#
Hosting/Install Wcf Services in a Windows Service Asp.Net C#
Connecting Silverlight to Wcf Asp.Net C#
Silverlight Data Grid Data Binding WCF Asp.Net C#
Invoking/Accessing/Calling WCF Service Without Adding/Creating Proxy/Reference Asp.Net C#
Performing Doing Creating Insert Update Delete sql data Using Linq Database Asp.Net C#
Concurrent Affairs: Solving The Dining Philosophers Problem With Asynchronous Agents
Learn Easily Using Video Tutorials
How to choose the right Java IDE – explained Eclipse NetBeans BlueJ
Developing/Creating/Performing/Configuring Java Applications Using Eclipse IDE
Step By Step Guide for Download/Install Configure Eclipse IDE for Java
Editing data with the GridView control Asp.Net C#
Registering/Configuring Web Controls globally in web.config file asp.net c#
Registering/Configuring Web Controls globally in web.config file asp.net c#
Best way to prepare asp.net Interview - Success Stories
Download Important Questions and PPT's:
Sql Server Important Questions Online free download
Dotnet Important Questions Online free download
Exploring Linq to Sql Process Flow
Learn how to perform silverlight programming
Learn OOPs concepts in better and well manner
Learn Ajax in better and well manner