Книга: Programming with POSIX® Threads

10.1.2 Mutex type

10.1.2 Mutex type

The DCE threads package provided an extension that allowed the programmer to specify the "kind" of mutex to be created. DCE threads supplied fast, recursive, and nonrecursive mutex kinds. The XSH5 specification changes the attribute name from "kind" to "type," renames fast to default, renames nonrecursive to errorcheck, and adds a new type, normal (Table 10.1).

A normal mutex is not allowed to detect deadlock errors — that is, a thread will hang if it tries to lock a normal mutex that it already owns. The default mutex type, like the DCE fast mutex,[11] provides implementation-defined error checking. That is, default may be mapped to one of the other standard types or may be something entirely different.

Mutex type  Definition
PTHREAD_MUTEX_NORMAL Basic mutex with no specific error checking built in. Does not report a deadlock error.
PTHREAD__MUTEX__RECURSIVE Allows any thread to lock the mutex "recursively" — it must unlock an equal number of times to release the mutex.
PTHREAD_MUTEX_ERRORCHECK Detects and reports simple usage errors — an attempt to unlock a mutex that's not locked by the calling thread (or that isn't locked at all), or an attempt to relock a mutex the thread already owns.
PTHREAD__MUTEX__DEFAULT The default mutex type, with very loose semantics to allow unfettered innovation and experimentation. May be mapped to any of the other three defined types, or may be something else entirely.

TABLE 10.1 XSH5 mutex types

As an application developer, you can use any of the mutex types almost interchangeably as long as your code does not depend on the implementation to detect (or fail to detect) any particular errors. Never write code that counts on an implementation Jailing to detect any error. Do not lock a mutex in one thread and unlock it in another thread, for example, even if you are sure that the error won't be reported — use a semaphore instead, which has no "ownership" semantics.

All mutexes, regardless of type, are created using pthread_mutex_init, destroyed using pthread_mutex_destroy, and manipulated using pthread_mutex_ lock, pthread_mutex_unlock, and pthread_mutex_trylock.

Normal mutexes will usually be the fastest implementation possible for the machine, but will provide the least error checking.

Recursive mutexes are primarily useful for converting old code where it is difficult to establish clear boundaries of synchronization, for example, when you must call a function with a mutex locked and the function you call — or some function it calls — may need to lock the same mutex. I have never seen a situation where recursive mutexes were required to solve a problem, but I have seen many cases where the alternate (and usually "better") solutions were impractical. Such situations frequently lead developers to create recursive mutexes, and it makes more sense to have a single implementation available to everyone. (But your code will usually be easier to follow, and perform better, if you avoid recursive mutexes.)

Errorcheck mutexes were devised as a debugging tool, although less intrusive debugging tools (where available) can be more powerful. To use errorcheck mutexes you must recompile code to turn the debugging feature on and off. It is far more useful to have an external option to force all mutexes to record debugging data. You may want to use errorcheck mutexes in final "production" code, of course, to detect serious problems early, but be aware that errorcheck mutexes will almost always be much slower than normal mutexes due to the extra state and checking.

Default mutexes allow each implementation to provide the mutex semantics the vendor feels will be most useful to the target audience. It may be useful to make errorcheck mutexes the default, for example, to improve the threaded debugging environment of a system. Or the vendor may choose to make normal mutexes the default to give most programs the benefit of any extra speed.

| pthread_mutexaftr_gettype

int pthread_mutexattr_gettype (

const pthread_mutexattr_t *attr,

int *type);

Specify the type of mutexes created with attr.

type

Unspecified type.

Basic mutex, with no error

checking.

PTHREAD_MUTEX_RECURSIVE Thread can relock a mutex it

owns.

PTHREAD_MUTEX_ERRORCHECK Checks for usage errors.

References: 3.2,5.2.1,10.1.2

Errors: [EINVAL] type invalid.

[EINVAL] attr invalid.

Hint: Normal mutexes will usually be fastest; errorcheck mutexes are use-

ful for debugging; recursive mutexes can be useful for making old interfaces thread-safe.

PTHREAD_MUTEX_DEFAULT

PTHREAD_MUTEX_NORMAL

pthread_mutexattr_settype

int pthread_mutexattr_settype (

pthread_mutexattr_t int

*attr, type);

Determine the type of mutexes created with attr.

type

PTHREAD_MUTEX_DEFAULT Unspecified type.

PTHREAD_MUTEX_NORMAL

Basic mutex, with no error checking.

PTHREAD_MUTEX_RECURSIVE Thread can relock a mutex it

owns.

PTHREAD_MUTEX_ERRORCHECK Checks for usage errors.

References: 3.2,5.2.1,10.1.2

Errors: [EINVAL] type invalid.

[EINVAL] attr invalid.

Hint: Normal mutexes will usually be fastest; errorcheck mutexes are use-

ful for debugging; recursive mutexes can be useful for making old interfaces thread-safe.

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


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