📄 threads.sgml
字号:
<!-- ##### SECTION Title ##### -->Threads<!-- ##### SECTION Short_Description ##### -->thread abstraction; including threads, different mutexes, conditionsand thread private data.<!-- ##### SECTION Long_Description ##### --><para>Threads act almost like processes, but unlike processes all threads ofone process share the same memory. This is good, as it provides easycommunication between the involved threads via this shared memory, andit is bad, because strange things (so called Heisenbugs) might happen,when the program is not carefully designed. Especially bad is, that dueto the concurrent nature of threads no assumptions on the order ofexecution of different threads can be done unless explicitly forced bythe programmer through synchronization primitives.</para><para>The aim of the thread related functions in GLib is to provide aportable means for writing multi-threaded software. There areprimitives for mutexes to protect the access to portions of memory(#GMutex, #GStaticMutex, #G_LOCK_DEFINE, #GStaticRecMutex and#GStaticRWLock), there are primitives for condition variables to allowsynchronization of threads (#GCond) and finally there are primitivesfor thread-private data, that every thread has a private instance of(#GPrivate, #GStaticPrivate). Last but definitely not least there areprimitives to portably create and manage threads (#GThread).</para><!-- ##### SECTION See_Also ##### --><para><variablelist><varlistentry><term>#GThreadPool</term><listitem><para>Thread pools.</para></listitem></varlistentry><varlistentry><term>#GAsyncQueue</term><listitem><para>Send asynchronous messages between threads.</para></listitem></varlistentry></variablelist></para><!-- ##### MACRO G_THREADS_ENABLED ##### --><para>This macro is defined, if GLib was compiled with thread support. Thisdoes not necessarily mean, that there is a thread implementationavailable, but the infrastructure is in place and once you provide athread implementation to g_thread_init(), GLib will be multi-threadsafe. It isn't and cannot be, if #G_THREADS_ENABLED is not defined.</para><!-- ##### MACRO G_THREADS_IMPL_POSIX ##### --><para>This macro is defined, if POSIX style threads are used.</para><!-- ##### MACRO G_THREADS_IMPL_SOLARIS ##### --><para>This macro is defined, if the Solaris thread system is used.</para><!-- ##### MACRO G_THREADS_IMPL_NONE ##### --><para>This macro is defined, if no thread implementation is used. You canhowever provide one to g_thread_init() to make GLib multi-thread safe.</para><!-- ##### MACRO G_THREAD_ERROR ##### --><para>The error domain of the GLib thread subsystem.</para><!-- ##### ENUM GThreadError ##### --><para>Possible errors of thread related functions.</para>@G_THREAD_ERROR_AGAIN: a thread couldn't be created due to resourceshortage. Try again later.<!-- ##### STRUCT GThreadFunctions ##### --><para>This function table is used by g_thread_init() to initialize thethread system. The functions in that table are directly used by theirg_* prepended counterparts, that are described here, e.g. if you callg_mutex_new() then mutex_new() from the table provided tog_thread_init() will be called.</para><note><para>This struct should only be used, if you know, what you are doing.</para></note>@mutex_new: @mutex_lock: @mutex_trylock: @mutex_unlock: @mutex_free: @cond_new: @cond_signal: @cond_broadcast: @cond_wait: @cond_timed_wait: @cond_free: @private_new: @private_get: @private_set: @thread_create: @thread_yield: @thread_join: @thread_exit: @thread_set_priority: @thread_self: @thread_equal: <!-- ##### FUNCTION g_thread_init ##### --><para>Before you use a thread related function in GLib, you shouldinitialize the thread system. This is done by callingg_thread_init(). Most of the time you will only have to call<literal>g_thread_init(NULL)</literal>. </para><note><para>You should only call g_thread_init() with a non-%NULL parameter if youreally know what you are doing.</para></note><note><para>g_thread_init() must not be called directly or indirectly as acallback from GLib. Also no mutexes may be currently locked, whilecalling g_thread_init().</para></note><para>g_thread_init() might only be called once. On the second callit will abort with an error. If you want to make sure, that the threadsystem is initialized, you can do that too:</para><para><informalexample><programlisting>if (!g_thread_supported (<!>)) g_thread_init (NULL);</programlisting></informalexample></para><para>After that line either the thread system is initialized or the programwill abort, if no thread system is available in GLib, i.e. either#G_THREADS_ENABLED is not defined or #G_THREADS_IMPL_NONE is defined.</para><para>If no thread system is available and @vtable is %NULL or if not allelements of @vtable are non-%NULL, then g_thread_init() will abort.</para><note><para>To use g_thread_init() in your program, you have to link with thelibraries that the command <command>pkg-config --libs gthread-2.0</command> outputs. This is not the case for all the other thread related functions ofGLib. Those can be used without having to link with the thread libraries.</para></note>@vtable: a function table of type #GThreadFunctions, that provides theentry points to the thread system to be used.<!-- ##### FUNCTION g_thread_supported ##### --><para>This function returns, whether the thread system is initialized ornot.</para><note><para>This function is actually a macro. Apart from taking the address of ityou can however use it as if it was a function.</para></note>@Returns: %TRUE, if the thread system is initialized.<!-- ##### USER_FUNCTION GThreadFunc ##### --><para>Specifies the type of the @func functions passed tog_thread_create() or g_thread_create_full().</para>@data: data passed to the thread.@Returns: the return value of the thread, which will be returned byg_thread_join().<!-- ##### ENUM GThreadPriority ##### --><para>Specifies the priority of a thread. </para><note><para>It is not guaranteed, that threads with different priorities reallybehave accordingly. On some systems (e.g. Linux) only root can increasepriorities. On other systems (e.g. Solaris) there doesn't seem to bedifferent scheduling for different priorities. All in all try to avoidbeing dependent on priorities.</para></note>@G_THREAD_PRIORITY_LOW: a priority lower than normal@G_THREAD_PRIORITY_NORMAL: the default priority@G_THREAD_PRIORITY_HIGH: a priority higher than normal@G_THREAD_PRIORITY_URGENT: the highest priority<!-- ##### STRUCT GThread ##### --><para>The #GThread struct represents a running thread. It has three publicread-only members, but the underlying struct is bigger, so you mustnot copy this struct.</para><note><para>Resources for a joinable thread are not fully released untilg_thread_join() is called for that thread.</para></note>@func: the function executing in that thread@data: the argument to the function@joinable: is this thread joinable?@priority: the priority of the thread<!-- ##### FUNCTION g_thread_create ##### --><para>This function creates a new thread with the priority @priority.</para><para>If @joinable is %TRUE, you can wait for this threads terminationcalling g_thread_join(). Otherwise the thread will just disappear, whenready. </para><para>The new thread executes the function @func with the argument@data. If the thread was created successfully, it is returned.</para><para>@error can be %NULL to ignore errors, or non-%NULL to report errors. Theerror is set, if and only if the function returns %NULL.</para>@func: a function to execute in the new thread.@data: an argument to supply to the new thread.@joinable: should this thread be joinable?@error: return location for error.@Returns: the new #GThread on success.<!-- ##### FUNCTION g_thread_create_full ##### --><para>This function creates a new thread with the priority @priority. Thestack gets the size @stack_size or the default value for the currentplatform, if @stack_size is 0.</para><para>If @joinable is %TRUE, you can wait for this threads terminationcalling g_thread_join(). Otherwise the thread will just disappear, whenready. If @bound is %TRUE, this thread will be scheduled in the systemscope, otherwise the implementation is free to do scheduling in theprocess scope. The first variant is more expensive resource-wise, butgenerally faster. On some systems (e.g. Linux) all threads are bound.</para><para>The new thread executes the function @func with the argument@data. If the thread was created successfully, it is returned.</para><para>@error can be %NULL to ignore errors, or non-%NULL to report errors. Theerror is set, if and only if the function returns %NULL.</para><note><para>It is not guaranteed, that threads with different priorities reallybehave accordingly. On some systems (e.g. Linux) only root can increasepriorities. On other systems (e.g. Solaris) there doesn't seem to bedifferent scheduling for different priorities. All in all try to avoidbeing dependent on priorities. Use %G_THREAD_PRIORITY_NORMAL here as adefault.</para></note><note><para>Only use g_thread_create_full(), when you really can't useg_thread_create() instead. g_thread_create() does not take@stack_size, @bound and @priority as arguments, as they should only beused for cases, where it is inevitable. </para></note>@func: a function to execute in the new thread.@data: an argument to supply to the new thread.@stack_size: a stack size for the new thread.@joinable: should this thread be joinable?@bound: should this thread be bound to a system thread?@priority: a priority for the thread.@error: return location for error.@Returns: the new #GThread on success.<!-- ##### FUNCTION g_thread_self ##### --><para>This functions returns the #GThread corresponding to the calling thread.</para>@Returns: the current thread.<!-- ##### FUNCTION g_thread_join ##### --><para>Waits until @thread finishes, i.e. the function @func, as givento g_thread_create(), returns or g_thread_exit() is called by@thread. All resources of @thread including the #GThread struct arereleased. @thread must have been created with @joinable=%TRUE ing_thread_create(). The value returned by @func or given tog_thread_exit() by @thread is returned by this function.</para>@thread: a #GThread to be waited for.@Returns: the return value of the thread.<!-- ##### FUNCTION g_thread_set_priority ##### --><para>Changes the priority of @thread to @priority.</para><note><para>It is not guaranteed, that threads with different priorities reallybehave accordingly. On some systems (e.g. Linux) only root can increasepriorities. On other systems (e.g. Solaris) there doesn't seem to bedifferent scheduling for different priorities. All in all try to avoidbeing dependent on priorities.</para></note>@thread: a #GThread.@priority: a new priority for @thread.<!-- ##### FUNCTION g_thread_yield ##### --><para>Gives way to other threads waiting to be scheduled. </para><para>This function is often used as a method to make busy wait lessevil. But in most cases, you will encounter, there are better methodsto do that. So in general you shouldn't use that function.</para><!-- ##### FUNCTION g_thread_exit ##### --><para>Exits the current thread. If another thread is waiting for that threadusing g_thread_join() and the current thread is joinable, the waitingthread will be woken up and getting @retval as the return value ofg_thread_join(). If the current thread is not joinable, @retval isignored. Calling</para><para><informalexample><programlisting>g_thread_exit (retval);</programlisting></informalexample></para><para>is equivalent to calling </para><para><informalexample><programlisting>return retval;</programlisting></informalexample></para><para>in the function @func, as given to g_thread_create().</para><note><para>Never call g_thread_exit() from within a thread of a #GThreadPool, asthat will mess up the bookkeeping and lead to funny and unwanted results.</para></note>@retval: the return value of this thread.<!-- ##### STRUCT GMutex ##### --><para>The #GMutex struct is an opaque data structure to represent a mutex(mutual exclusion). It can be used to protect data against sharedaccess. Take for example the following function:<example><title>A function which will not work in a threaded environment</title><programlisting> int give_me_next_number (<!>) { static int current_number = 0; /* now do a very complicated calculation to calculate the new number, this might for example be a random number generator */ current_number = calc_next_number (current_number); return current_number; }</programlisting></example></para><para>It is easy to see, that this won't work in a multi-threadedapplication. There current_number must be protected against sharedaccess. A first naive implementation would be:</para><para><example><title>The wrong way to write a thread-safe function</title><programlisting> int give_me_next_number (<!>) { static int current_number = 0; int ret_val; static GMutex * mutex = NULL; if (!mutex) mutex = g_mutex_new (); g_mutex_lock (mutex); ret_val = current_number = calc_next_number (current_number); g_mutex_unlock (mutex); return ret_val; }</programlisting></example></para><para>This looks like it would work, but there is a race condition whileconstructing the mutex and this code cannot work reliable. So please donot use such constructs in your own programs. One working solution is:</para><para><example><title>A correct thread-safe function</title><programlisting> static GMutex *give_me_next_number_mutex = NULL; /* this function must be called before any call to give_me_next_number (<!>) it must be called exactly once. */ void init_give_me_next_number (<!>) { g_assert (give_me_next_number_mutex == NULL); give_me_next_number_mutex = g_mutex_new (<!>); } int give_me_next_number (<!>) { static int current_number = 0; int ret_val; g_mutex_lock (give_me_next_number_mutex); ret_val = current_number = calc_next_number (current_number); g_mutex_unlock (give_me_next_number_mutex); return ret_val; }</programlisting></example></para><para>#GStaticMutex provides a simpler and safer way of doing this.</para><para>If you want to use a mutex, but your code should also work withoutcalling g_thread_init() first, you can not use a #GMutex, as
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -