Threads and Mutexes — Part II
Welcome to the second part of our look at programming with threads. In last month's column we talked about the functions that allow you to create and wait on threads. This month we're going to dive deeper into the problems that often arise when using threads to write concurrent programs. Before we begin that however, we'll return to the ticket agent example we looked at last month and discuss the solution to the problem of over-selling of tickets.
Thursday, March 15th, 2001
Welcome to the second part of our look at programming with threads. In last month’s column we talked about the functions that allow you to create and wait on threads. This month we’re going to dive deeper into the problems that often arise when using threads to write concurrent programs. Before we begin that however, we’ll return to the ticket agent example we looked at last month and discuss the solution to the problem of over-selling of tickets.
One quick note before we proceed: If you’re writing applications that use the pthreads libraries for Linux, you must include the option -lpthread as a flag to the compiler on the command line. This will tell the compiler and linker to look for the necessary functions in the pthreads library and link them into your application.
The Ticket Agency
As we saw last month, using threads allows you to have multiple pieces of code that share and operate on a common set of data. However, threads introduce additional complexity and create code that is often difficult to debug. Let’s return to our ticket agency example. Each ticket agent may be thought of as one thread. There is common data between the ticket agents — the number of tickets to be sold. Our goal is to sell all the tickets without selling too many. Each ticket agent can be modeled with the C function:
void* ticket_agent (void* foo)
{
while (total_sold < NUM_TICKETS)
{
if (sold_ticket ())
total_sold++;
}
return NULL;
}
Figure One: The ticket_agent() Function
int main ()
{
pthread_t agents[NUM_AGENTS];
void* return_val;
int i;
srand (time (0));
for (i = 0; i < NUM_AGENTS; i++)
pthread_create (&agents[i], NULL, ticket_agent, NULL);
for (i = 0; i < NUM_AGENTS; i++)
pthread_join (agents[i], &return_val);
printf (“%d\n”, total_sold);
return 0;
}
|
Then ticket agents can be created as threads in the main() function, as shown in Figure One. This program seems simple. Ticket agents should sell tickets until they’re all gone. Then, the main() function prints out the total number of tickets sold. However, if we actually run this program, we get some disturbing results. We need to add a few global variables:
#define NUM_TICKETS 10000000
#define NUM_AGENTS 4
int total_sold = 0;
Linux Magazine /
March 2001 / COMPILE TIME
Threads and Mutexes: Part II