Книга: Programming with POSIX® Threads

3.2.1 Creating and destroying a mutex

3.2.1 Creating and destroying a mutex

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int pthread_mutex_init (

pthread_mutex_t *mutex, pthread_mutexattr_t *attr); int pthread_mutex_destroy (pthread_mutex_t *mutex);

A mutex is represented in your program by a variable of type pthread_mutex_t. You should never make a copy of a mutex, because the result of using a copied mutex is undefined. You can, however, freely copy a pointer to a mutex so that various functions and threads can use it for synchronization.

Most of the time you'll probably declare mutexes using extern or static storage class, at "file scope," that is, outside of any function. They should have "normal" (extern) storage class if they are used by other files, or static storage class if used only within the file that declares the variable. When you declare a static mutex that has default attributes, you should use the PTHREAD_MUTEX_ INITIALIZER macro, as shown in the mutex_static.c program shown next. (You can build and run this program, but don't expect anything interesting to happen, since main is empty.)

mutex_static.c

1 #include <pthread.h>
2 #include "errors.h"
3
4 /*
5 * Declare a structure, with a mutex, statically initialized. This
6 * is the same as using pthread_mutex_init, with the default
7 * attributes.
8 */
9 typedef struct my_struct_tag {
10 pthread_mutex_t  mutex; /* Protects access to value */
11 int       value; /* Access protected by mutex */
12 } my_struct_t; 13
14 my_struct_t data = {PTHREAD_MUTEX_INITIALIZER, 0};
15
16 int main (int argc, char *argv[])
17 {
18 return 0;
19 }

Often you cannot initialize a mutex statically, for example, when you use malloc to create a structure that contains a mutex. Then you will need to call pthread_mutex_init to initialize the mutex dynamically, as shown in mutex_ dynamic.c, the next program. You can also dynamically initialize a mutex that you declare statically—but you must ensure that each mutex is initialized before it is used, and that each is initialized only once. You may initialize it before creating any threads, for example, or by calling pthread_once (Section 5.1). Also, if you need to initialize a mutex with nondefault attributes, you must use dynamic initialization (see Section 5.2.1).

? mutex_dynamic.c

1 #include <pthread.h>
2 #include "errors.h" 3
4 /*
5 * Define a structure, with a mutex.
6 */
7 typedef struct my_struct_tag {
8 pthread_mutex_t mutex; /* Protects access to value */
9 int value; /* Access protected by mutex */ 10 } my_struct_t;
11
12 int main (int argc, char *argv[])
13 {
14 my_struct_t *data;
15 int status;
16
17 data = malloc (sizeof (my_struct_t));
18 if (data == NULL)
19 errno_abort ("Allocate structure");
20 status = pthread_mutex_init (&data->mutex, NULL);
21 if (status != 0)
22 err_abort (status, "Init mutex");
23 status = pthread_mutex_destroy (&data->mutex);
24 if (status != 0)
25 err_abort (status, "Destroy mutex");
26 (void)free (data);
27 return status;
28 }

It is a good idea to associate a mutex clearly with the data it protects, if possible, by keeping the definition of the mutex and data together. In mutex_static.c and mutex_dynamic.c for example, the mutex and the data it protects are defined in the same structure, and line comments document the association.

When you no longer need a mutex that you dynamically initialized by calling pthread_mutex_init, you should destroy the mutex by calling pthread_mutex_ destroy. You do not need to destroy a mutex that was statically initialized using

the PTHREAD_MUTEX_INITIALIZER macro.

You can destroy a mutex as soon as you are sure no threads are blocked on the mutex.

It is safe to destroy a mutex when you know that no threads can be blocked on the mutex, and no additional threads will try to lock the mutex. The best way to know this is usually within a thread that has just unlocked the mutex, when program logic ensures that no threads will try to lock the mutex later. When a thread locks a mutex within some heap data structure to remove the structure from a list and free the storage, for example, it is safe (and a good idea) to unlock and destroy the mutex before freeing the storage that the mutex occupies.

Оглавление книги


Генерация: 1.157. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз