📄 posix threads programming.htm
字号:
<LI>The <TT>pthread_detach()</TT> routine can be used to explicitly detach a
thread even though it was created as joinable. There is no converse routine.
<P></P>
<LI>The final draft of the POSIX standard specifies that threads should be
created as joinable. However, not all implementations may follow this.
<P></P>
<LI>Recommendations:
<UL>
<LI>If a thread requires joining, consider explicitly creating it as
joinable. This provides portability as not all implementations may create
threads as joinable by default.
<LI>If you know in advance that a thread will never need to join with
another thread, consider creating it in a detached state. Some system
resources may be able to be freed. </LI></UL></LI></UL><!---------------------------------------------------------------------------><A
name=JoiningExample><BR><BR></A>
<TABLE cellSpacing=0 cellPadding=5 width="100%" border=1>
<TBODY>
<TR>
<TD background="POSIX Threads Programming.files/bg2.gif"
bgColor=navy><SPAN class=heading1>Thread Management
</SPAN></TD></TD></TR></TBODY></TABLE>
<P><SPAN class=heading2>Example: Pthread Joining </SPAN>
<P><BR>
<UL>
<P>
<TABLE cellSpacing=0 cellPadding=5 width="90%" border=1>
<TBODY>
<TR>
<TD bgColor=#eeeeee><IMG height=22
src="POSIX Threads Programming.files/page01.gif" width=20 align=top>
<B><SPAN class=heading3>Example Code - Pthread Joining</SPAN></B>
<UL>This example demonstrates how to "wait" for thread completions by
using the Pthread join routine. Since not all current implementations
of Pthreads create threads in a joinable state, the threads in this
example are explicitly created in a joinable state so that they can be
joined later. </UL>
<HR>
<FONT size=-1><PRE><B>
<FONT color=red>#include <pthread.h></FONT>
#include <stdio.h>
#define NUM_THREADS 3
void *BusyWork(void *null)
{
int i;
double result=0.0;
for (i=0; i < 1000000; i++)
{
result = result + (double)random();
}
printf("result = %e\n",result);
<FONT color=red>pthread_exit((void *) 0);</FONT>
}
int main (int argc, char *argv[])
{
<FONT color=red>pthread_t thread[NUM_THREADS];</FONT>
<FONT color=red>pthread_attr_t attr;</FONT>
int rc, t, status;
/* Initialize and set thread detached attribute */
<FONT color=red>pthread_attr_init(&attr);</FONT>
<FONT color=red>pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);</FONT>
for(t=0;t < NUM_THREADS;t++)
{
printf("Creating thread %d\n", t);
<FONT color=red>rc = pthread_create(&thread[t], &attr, BusyWork, NULL); </FONT>
if (rc)
{
printf("ERROR; return code from pthread_create()
is %d\n", rc);
exit(-1);
}
}
/* Free attribute and wait for the other threads */
<FONT color=red>pthread_attr_destroy(&attr);</FONT>
for(t=0;t < NUM_THREADS;t++)
{
<FONT color=red> rc = pthread_join(thread[t], (void **)&status);</FONT>
if (rc)
{
printf("ERROR; return code from pthread_join()
is %d\n", rc);
exit(-1);
}
printf("Completed join with thread %d status= %d\n",t, status);
}
<FONT color=red>pthread_exit(NULL);</FONT>
}
</B></PRE><A onclick=blur()
href="http://www.llnl.gov/computing/tutorials/workshops/workshop/pthreads/samples/join1.c"
target=W2><IMG height=20 alt="View source code"
src="POSIX Threads Programming.files/source1.gif" width=65 border=0></A>
<A onclick=blur()
href="http://www.llnl.gov/computing/tutorials/workshops/workshop/pthreads/samples/join1.out"
target=W2><IMG height=20 alt="View sample output"
src="POSIX Threads Programming.files/output1.gif" width=65 border=0></A>
</FONT></TD></TR></TBODY></TABLE></P></UL><!---------------------------------------------------------------------------><A
name=Mutexes><BR><BR></A><A name=MutexOverview></A>
<TABLE cellSpacing=0 cellPadding=5 width="100%" border=1>
<TBODY>
<TR>
<TD background="POSIX Threads Programming.files/bg2.gif"
bgColor=navy><SPAN class=heading1>Mutex Variables
</SPAN></TD></TD></TR></TBODY></TABLE>
<P><SPAN class=heading2>Overview </SPAN>
<P><BR>
<UL>
<P>
<LI>Mutex is an abbreviation for "mutual exclusion". Mutex variables are one
of the primary means of implementing thread synchronization and for protecting
shared data when multiple writes occur.
<P></P>
<LI>A mutex variable acts like a "lock" protecting access to a shared data
resource. The basic concept of a mutex as used in Pthreads is that only one
thread can lock (or own) a mutex variable at any given time. Thus, even if
several threads try to lock a mutex only one thread will be successful. No
other thread can own that mutex until the owning thread unlocks that mutex.
Threads must "take turns" accessing protected data.
<P></P>
<LI>Mutexes can be used to prevent "race" conditions. An example of a race
condition involving a bank transaction is shown below:
<P>
<TABLE cellSpacing=0 cellPadding=5 width="90%" border=1>
<TBODY>
<TR>
<TH bgColor=#eeeeee><SPAN class=heading3>Thread 1</SPAN></TH>
<TH bgColor=#eeeeee><SPAN class=heading3>Thread 2</SPAN></TH>
<TH bgColor=#eeeeee><SPAN class=heading3>Balance</SPAN></TH></TR>
<TR>
<TD>Read balance: $1000</TD>
<TD> </TD>
<TD>$1000</TD></TR>
<TR>
<TD> </TD>
<TD>Read balance: $1000</TD>
<TD>$1000</TD></TR>
<TR>
<TD> </TD>
<TD>Deposit $200</TD>
<TD>$1000</TD></TR>
<TR>
<TD>Deposit $200</TD>
<TD> </TD>
<TD>$1000</TD></TR>
<TR>
<TD>Update balance $1000+$200</TD>
<TD> </TD>
<TD>$1200</TD></TR>
<TR>
<TD> </TD>
<TD>Update balance $1000+$200</TD>
<TD>$1200</TD></TR></TD></TBODY></TABLE>
<P></P>
<LI>In the above example, a mutex should be used to lock the "Balance" while a
thread is using this shared data resource.
<P></P>
<LI>Very often the action performed by a thread owning a mutex is the updating
of global variables. This is a safe way to ensure that when several threads
update the same variable, the final value is the same as what it would be if
only one thread performed the update. The variables being updated belong to a
"critical section".
<P></P>
<LI>A typical sequence in the use of a mutex is as follows:
<UL>
<LI>Create and initialize a mutex variable
<LI>Several threads attempt to lock the mutex
<LI>Only one succeeds and that thread owns the mutex
<LI>The owner thread performs some set of actions
<LI>The owner unlocks the mutex
<LI>Another thread acquires the mutex and repeats the process
<LI>Finally the mutex is destroyed </LI></UL>
<P></P>
<LI>When several threads compete for a mutex, the losers block at that call -
an unblocking call is available with "trylock" instead of the "lock" call.
<P></P>
<LI>When protecting shared data, it is the programmer's responsibility to make
sure every thread that needs to use a mutex does so. For example, if 4 threads
are updating the same data, but only one uses a mutex, the data can still be
corrupted. </LI></UL><!---------------------------------------------------------------------------><A
name=MutexCreation><BR><BR></A>
<TABLE cellSpacing=0 cellPadding=5 width="100%" border=1>
<TBODY>
<TR>
<TD background="POSIX Threads Programming.files/bg2.gif"
bgColor=navy><SPAN class=heading1>Mutex Variables
</SPAN></TD></TD></TR></TBODY></TABLE>
<P><SPAN class=heading2>Creating / Destroying Mutexes </SPAN>
<P><BR>
<UL>
<P>
<LI>Routines:
<P>
<TABLE cellSpacing=0 cellPadding=5 width="90%" border=1>
<TBODY>
<TR>
<TD bgColor=#eeeeee><TT><B><A onclick=blur()
href="http://www.llnl.gov/computing/tutorials/workshops/workshop/pthreads/man/pthread_mutex_init.html"
target=W2>pthread_mutex_init</A> (mutex,attr)
<P><A onclick=blur()
href="http://www.llnl.gov/computing/tutorials/workshops/workshop/pthreads/man/pthread_mutex_destroy.html"
target=W2>pthread_mutex_destroy</A> (mutex)
<P><A onclick=blur()
href="http://www.llnl.gov/computing/tutorials/workshops/workshop/pthreads/man/pthread_mutexattr_init.html"
target=W2>pthread_mutexattr_init</A> (attr)
<P><A onclick=blur()
href="http://www.llnl.gov/computing/tutorials/workshops/workshop/pthreads/man/pthread_mutexattr_destroy.html"
target=W2>pthread_mutexattr_destroy</A> (attr)
</P></B></TT></TD></TR></TBODY></TABLE>
<P></P>
<LI>Mutex variables must be declared with type <TT>pthread_mutex_t</TT>, and
must be initialized before they can be used. There are two ways to initialize
a mutex variable:
<OL>
<P>
<LI>Statically, when it is declared. For example: <BR><TT>pthread_mutex_t
mymutex = PTHREAD_MUTEX_INITIALIZER;</TT>
<P></P>
<LI>Dynamically, with the <TT>pthread_mutex_init()</TT> routine. This method
permits setting mutex object attributes, <I>attr</I>. </LI></OL>
<P>The mutex is initially unlocked.
<P></P>
<LI>The <I>attr</I> object is used to establish properties for the mutex
object, and must be of type <TT>pthread_mutexattr_t</TT> if used (may be
specified as NULL to accept defaults). The Pthreads standard defines three
optional mutex attributes:
<UL>
<LI>Protocol: Specifies the protocol used to prevent priority inversions for
a mutex.
<LI>Prioceiling: Specifies the priority ceiling of a mutex.
<LI>Process-shared: Specifies the process sharing of a mutex. </LI></UL>
<P>Note that not all implementations may provide the three optional mutex
attributes.
<P></P>
<LI>The <TT>pthread_mutexattr_init()</TT> and
<TT>pthread_mutexattr_destroy()</TT> routines are used to create and destroy
mutex attribute objects respectively.
<P></P>
<LI><TT>pthread_mutex_destroy()</TT> should be used to free a mutex object
which is no longer needed. </LI></UL><!---------------------------------------------------------------------------><A
name=MutexLocking><BR><BR></A>
<TABLE cellSpacing=0 cellPadding=5 width="100%" border=1>
<TBODY>
<TR>
<TD background="POSIX Threads Programming.files/bg2.gif"
bgColor=navy><SPAN class=heading1>Mutex Variables
</SPAN></TD></TD></TR></TBODY></TABLE>
<P><SPAN class=heading2>Locking / Unlocking Mutexes </SPAN>
<P><BR>
<UL>
<P>
<LI>Routines:
<P>
<TABLE cellSpacing=0 cellPadding=5 width="90%" border=1>
<TBODY>
<TR>
<TD bgColor=#eeeeee><TT><B><A onclick=blur()
href="http://www.llnl.gov/computing/tutorials/workshops/workshop/pthreads/man/pthread_mutex_lock.html"
target=W2>pthread_mutex_lock</A> (mutex)
<P><A onclick=blur()
href="http://www.llnl.gov/computing/tutorials/workshops/workshop/pthreads/man/pthread_mutex_trylock.html"
target=W2>pthread_mutex_trylock</A> (mutex)
<P><A onclick=blur()
href="http://www.llnl.gov/computing/tutorials/workshops/workshop/pthreads/man/pthread_mutex_unlock.html"
target=W2>pthread_mutex_unlock</A> (mutex)
</P></B></TT></TD></TR></TBODY></TABLE>
<P></P>
<LI>The <TT>pthread_mutex_lock()</TT> routine is used by a thread to acquire a
lock on the specified <I>mutex</I> variable. If the mutex is already locked by
another thread, this call will block the calling thread until the mutex is
unlocked.
<P></P>
<LI><TT>pthread_mutex_trylock()</TT> will attempt to lock a mutex. However, if
the mutex is already locked, the routine will return immediately with a "busy"
error code. This routine may be useful in preventing deadlock conditions, as
in a priority-inversion situation.
<P></P>
<LI><TT>pthread_mutex_unlock()</TT> will unlock a mutex if called by the
owning thread. Calling this routine is required after a thread has completed
its use of protected data if other threads are to acquire the mutex for their
work with the protected data. An error will be returned if:
<UL>
<LI>If the mutex was already unlocked
<LI>If the mutex is owned by another thread </LI></UL>
<P></P>
<LI>There is nothing "magical" about mutexes...in fact they are akin to a
"gentlemen's agreement" between participating threads. It is up to the code
writer to insure that the necessary threads all make the the mutex lock and
unlock calls correctly. The following scenario demonstrates a logical error: <PRE> <B>Thread 1 Thread 2 Thread 3</B>
Lock Lock
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -