<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="gl">
	<id>http://web.iesrodeira.com/mediawiki/index.php?action=history&amp;feed=atom&amp;title=Programaci%C3%B3n_con_Threads_baixo_Linux</id>
	<title>Programación con Threads baixo Linux - Historial de revisións</title>
	<link rel="self" type="application/atom+xml" href="http://web.iesrodeira.com/mediawiki/index.php?action=history&amp;feed=atom&amp;title=Programaci%C3%B3n_con_Threads_baixo_Linux"/>
	<link rel="alternate" type="text/html" href="http://web.iesrodeira.com/mediawiki/index.php?title=Programaci%C3%B3n_con_Threads_baixo_Linux&amp;action=history"/>
	<updated>2026-04-09T06:51:51Z</updated>
	<subtitle>Historial de revisións desta páxina no wiki</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://web.iesrodeira.com/mediawiki/index.php?title=Programaci%C3%B3n_con_Threads_baixo_Linux&amp;diff=1826&amp;oldid=prev</id>
		<title>Xavi: Nova páxina: &quot;== Programación con Threads Baixo Linux == En Linux existen moitas librerías que implementan os threads de execución xa que, a diferencia dos procesos (&#039;&#039;fork&#039;&#039;), non forman pa...&quot;</title>
		<link rel="alternate" type="text/html" href="http://web.iesrodeira.com/mediawiki/index.php?title=Programaci%C3%B3n_con_Threads_baixo_Linux&amp;diff=1826&amp;oldid=prev"/>
		<updated>2014-06-26T09:19:41Z</updated>

		<summary type="html">&lt;p&gt;Nova páxina: &amp;quot;== Programación con Threads Baixo Linux == En Linux existen moitas librerías que implementan os threads de execución xa que, a diferencia dos procesos (&amp;#039;&amp;#039;fork&amp;#039;&amp;#039;), non forman pa...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Páxina nova&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Programación con Threads Baixo Linux ==&lt;br /&gt;
En Linux existen moitas librerías que implementan os threads de execución xa que, a diferencia dos procesos (&amp;#039;&amp;#039;fork&amp;#039;&amp;#039;), non forman parte do kernel do sistema. Probablemente a librería de threads máis utilizada sexa a librería &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; que é a que imos a estudiar. &lt;br /&gt;
&lt;br /&gt;
Para utilizar a librería &amp;#039;&amp;#039;&amp;#039;pthread&amp;#039;&amp;#039;&amp;#039; é necesario incluir o ficheiro de cabeceira &amp;#039;&amp;#039;&amp;#039;pthread.h&amp;#039;&amp;#039;&amp;#039; (&amp;#039;&amp;#039;#include &amp;lt;pthread.h&amp;gt;&amp;#039;&amp;#039;) e cando se compile o programa enlazalo coa librería (&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;-lpthread&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;). &lt;br /&gt;
&lt;br /&gt;
As funcións de manexo de threads son as seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Creación do Thread&amp;lt;/u&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
int pthread_create (pthread_t *thread, pthread_attr_t *attr, &lt;br /&gt;
                    void *(*start_routine)(void *), void * arg);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta función crea un novo thread de execución que levará a cabo a función &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;start_routine&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; ó mesmo tempo que o thread principal. A función &amp;#039;&amp;#039;&amp;#039;start_routine&amp;#039;&amp;#039;&amp;#039; debe ter o seguinte prototipo: &lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
void * start_routine (void *param);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O parámetro &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;arg&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; é a información que se lle pasará como parámetro á función &amp;#039;&amp;#039;&amp;#039;start_routine&amp;#039;&amp;#039;&amp;#039;. Si a rutina non precisa de ningún argumento, se &amp;#039;&amp;#039;&amp;#039;poñerá NULL&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
O parámetro &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;thread&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; é a dirección de memoria dunha variable de tipo &amp;#039;&amp;#039;&amp;#039;pthread_t&amp;#039;&amp;#039;&amp;#039; onde se almacenará a información do novo thread creado.&lt;br /&gt;
&lt;br /&gt;
O parámetro &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;attr&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; contén os atributos que vai ter o novo thread (&amp;#039;&amp;#039;ver as funcións de manexo de atributos&amp;#039;&amp;#039;). &amp;#039;&amp;#039;&amp;#039;Se queremos os atributos por defecto, poñeremos NULL&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Facer que o thread principal espere a que rematen os threads en execución:&amp;lt;/u&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
int pthread_join (pthread_t th, void **pthread_return);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A función &amp;#039;&amp;#039;pthread_join&amp;#039;&amp;#039; fai que a función que o chama (o thread principal) espere pola finalización dos threads secundarios antes de rematar, de xeito que poda liberar os seus recursos.&lt;br /&gt;
&lt;br /&gt;
O parámetro &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;th&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; é o thread polo que se vai esperar a que finalice.&lt;br /&gt;
&lt;br /&gt;
O parámetro &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_return&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; almacenará o valor devolto polo thread finalizado.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Finalizar a execución do thread actual&amp;lt;/u&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
void pthread_exit (void *retval);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta función provoca a finalización do thread en execución devolvendo o valor &amp;#039;&amp;#039;&amp;#039;retval&amp;#039;&amp;#039;&amp;#039;. É o equivalente a escribir &amp;#039;&amp;#039;&amp;#039;return retval&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&amp;#039;Independizar&amp;#039; a execución do fío do que o creou (garantizar que o fío libere os seus recursos o finalizar)&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
int pthread_detach (pthread_t th);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esta función fai que o thread &amp;#039;&amp;#039;&amp;#039;th&amp;#039;&amp;#039;&amp;#039; se execute de xeito independiente do thread principal, e decir, que unha vez finalizado liberará os seus recursos por si mesmo. A un thread &amp;#039;&amp;#039;detached&amp;#039;&amp;#039; con esta función non se lle poderá facer un &amp;#039;&amp;#039;pthread_join&amp;#039;&amp;#039; pra esperar pola súa finalización.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Manexo dos atributos do thread que se vai a crear&amp;lt;/u&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
int pthread_attr_init (pthread_attr_t *attr);&lt;br /&gt;
int pthread_attr_destroy(pthread_attr_t *attr);&lt;br /&gt;
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);&lt;br /&gt;
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);&lt;br /&gt;
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int schedpolicy);&lt;br /&gt;
int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *schedpolicy);&lt;br /&gt;
int pthread_attr_setschedparam(pthread_attr_t *attr, int schedparam);&lt;br /&gt;
int pthread_attr_getschedparam(pthread_attr_t *attr, int *schedparam);&lt;br /&gt;
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);&lt;br /&gt;
int pthread_attr_getinheritsched(pthread_attr_t *attr, int *inheritsched);&lt;br /&gt;
int pthread_attr_setscope(pthread_attr_t *attr, int scope);&lt;br /&gt;
int pthread_attr_getscope(pthread_attr_t *attr, int *scope);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Para poñer os atributos a un thread, se debe encher primeiro unha estructura de tipo &amp;#039;&amp;#039;&amp;#039;pthread_attr_t&amp;#039;&amp;#039;&amp;#039; e logo pasarllo como argumento á función &amp;#039;&amp;#039;&amp;#039;pthread_create&amp;#039;&amp;#039;&amp;#039;, si a esta función lle pasamos NULL como atributo o thread collerá os atributos por defecto. A función &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_attr_init&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; inicializa o parámetro &amp;#039;&amp;#039;&amp;#039;attr&amp;#039;&amp;#039;&amp;#039; cos atributos por defecto dos threads, mentras que &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_attr_destroy&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; elimina os atributos que se crearon &amp;#039;&amp;#039;&amp;#039;(en Linux non ten efecto)&amp;#039;&amp;#039;&amp;#039;. Pra manipular os distintos atributos que teñen os threads utilízanse o resto das funcións, sendo as funcións que comenzan por &amp;#039;&amp;#039;&amp;#039;pthread_attr_set&amp;#039;&amp;#039;&amp;#039; pra poñer atributos e as que comenzan por &amp;#039;&amp;#039;&amp;#039;pthread_attr_get&amp;#039;&amp;#039;&amp;#039; pra saber que atributos ten. Os atributos que se poden manipular son:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;detachstate&amp;#039;&amp;#039;&amp;#039; : controla si o thread se crea nun estado no que se pode facer un &amp;#039;&amp;#039;&amp;#039;pthread_join&amp;#039;&amp;#039;&amp;#039; (&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;PTHREAD_CREATE_JOINABLE&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;) ou en estado desenganchado (como si lle fixeramos un &amp;#039;&amp;#039;&amp;#039;pthread_detach&amp;#039;&amp;#039;&amp;#039;) (&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;PTHREAD_CREATE_DETACHED&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;). O valor por defecto é &amp;#039;&amp;#039;&amp;#039;PTHREAD_CREATE_JOINABLE&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;schedpolicy&amp;#039;&amp;#039;&amp;#039;: controla a &amp;#039;&amp;#039;política de planificación&amp;#039;&amp;#039; do proceso (sheduling) vinculados ó thread creado. Pode ser &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;SCHED_OTHER&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (planificación normal), &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;SCHED_RR&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039; (round robin ou roubo de ciclo) ou &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;SCHED_FIFO&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (planificación FIFO, tamén chamada FCFS (First Comed First Served)). O valor por defecto é &amp;#039;&amp;#039;&amp;#039;SCHED_OTHER&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;schedparam&amp;#039;&amp;#039;&amp;#039;: conten os parámetros da política de planificación de procesos empregada no thread, normalmente a súa prioridade de execución. &amp;#039;&amp;#039;&amp;#039;Por defecto a prioridade é 0&amp;#039;&amp;#039;&amp;#039; é unicamente ten sentido coas políticas &amp;#039;&amp;#039;&amp;#039;SCHED_FIFO&amp;#039;&amp;#039;&amp;#039; e &amp;#039;&amp;#039;&amp;#039;SCHED_RR&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;inheritsched&amp;#039;&amp;#039;&amp;#039;: Indica si as políticas de planificación e os seus parámetros se collen do proceso que lanza o thread (&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;PTHREAD_INHERIT_SCHED&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;) ou dos atributos indicados (schedpolicy e schedparam) no momento de crear o thread (&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;PTHREAD_EXPLICIT_SCHED&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;). Por defecto é &amp;#039;&amp;#039;&amp;#039;PTHREAD_EXPLICIT_SCHED&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;scope&amp;#039;&amp;#039;&amp;#039;: O único valor soportado en Linux é &amp;#039;&amp;#039;&amp;#039;PTHREAD_SCOPE_SYSTEM&amp;#039;&amp;#039;&amp;#039; que indica que os threads competirán co resto dos procesos do sistema pra utilizar a CPU. O outro valor especificado polo estándar &amp;#039;&amp;#039;&amp;#039;pero non soportado en Linux&amp;#039;&amp;#039;&amp;#039; é &amp;#039;&amp;#039;&amp;#039;PTHREAD_SCOPE_PROCESS&amp;#039;&amp;#039;&amp;#039; que indica que os threads únicamente compiten co resto de threads do proceso en funcionamento.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mutex, Semáforos e Condicións de Sincronización ===&lt;br /&gt;
&lt;br /&gt;
Supoñamos que temos un programa que lanza dous fíos de execución para atender conexións e vender entradas pra un espectáculo e que inicialmente temos 100 entradas. Deste xeito poderemos atender ós clientes de dous en dous. &lt;br /&gt;
&lt;br /&gt;
Para vender as entradas cada fío comproba si quedan entradas (inicialmente temos 100). Si quedan, realiza a venta restándolle 1 ó número de entradas que quedan por vender. &lt;br /&gt;
&lt;br /&gt;
A primeira vista este algoritmo é correcto, pero supoñamos que queda 1 entrada por vender e solicitan unha compra dous clientes ó mesmo tempo. Cada thread atenderá a un cliente; en primeiro lugar comprobarán si quedan entradas, vendo ambos threads que queda unha entrada e procedendo a efectuar a venta. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;¡ Como resultado venderase unha entrada de máis !&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
Este tipo de situacións reciben o nome de &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;condicións de competencia&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; ou &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;condicións de carreira&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; (&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;racing condition&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;), xa que varios procesos compiten por un recurso. Para solucionalas os threads proporcionan &amp;#039;&amp;#039;&amp;#039;Mutex&amp;#039;&amp;#039;&amp;#039;, &amp;#039;&amp;#039;&amp;#039;Semáforos&amp;#039;&amp;#039;&amp;#039; e  as &amp;#039;&amp;#039;&amp;#039;Condicións de Sincronización&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
==== Mutex ====&lt;br /&gt;
&lt;br /&gt;
Os &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; permiten bloquear unha parte do código, de xeito que ningún outro fío de execución poda acceder a él mentras non se libere o bloqueo. Deste xeito, si os threads bloquean o código que comproba o número de entradas que quedan e lo liberan despois de realizada a venta, obligamos a que primeiro execute a parte crítica un proceso e logo o outro. &lt;br /&gt;
&lt;br /&gt;
As funcións de manexo de &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;mutex&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; son as seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
   pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;&lt;br /&gt;
   pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;&lt;br /&gt;
   pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;&lt;br /&gt;
   int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);&lt;br /&gt;
   int pthread_mutex_lock(pthread_mutex_t *mutex);&lt;br /&gt;
   int pthread_mutex_trylock(pthread_mutex_t *mutex);&lt;br /&gt;
   int pthread_mutex_unlock(pthread_mutex_t *mutex);&lt;br /&gt;
   int pthread_mutex_destroy(pthread_mutex_t *mutex);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;mutex&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; é un dispositivo de &amp;#039;&amp;#039;&amp;#039;ex&amp;#039;&amp;#039;&amp;#039;clusión &amp;#039;&amp;#039;&amp;#039;mu&amp;#039;&amp;#039;&amp;#039;tua útil pra protexer estructuras de datos compartidas de modificacións concurrentes, e para implementar &amp;#039;&amp;#039;rexións críticas&amp;#039;&amp;#039; e &amp;#039;&amp;#039;monitores&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
Os &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; teñen dous estados posibles: &amp;#039;&amp;#039;&amp;#039;unlocked&amp;#039;&amp;#039;&amp;#039; (libre, non ocupado por ningún thread) ou &amp;#039;&amp;#039;&amp;#039;locked&amp;#039;&amp;#039;&amp;#039; (ocupado por un thread). Un &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; nunca pode estar ocupado por máis de un thread.&lt;br /&gt;
&lt;br /&gt;
Si un thread intenta ocupar un &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; xa ocupado, quedará a espera de que o thread que ten o &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; o libere.&lt;br /&gt;
&lt;br /&gt;
A función &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_mutex_init&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; inicializa o obxecto &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; indicado polo parámetro mutex de acordo cos atributos indicados no parametro mutexattr. Si o parámetro mutexattr é NULL, utilizaránse atributos por defecto. &lt;br /&gt;
&lt;br /&gt;
A implementación de Linux dos Threads (pthreads) únicamente soporta un atributo para os mutex: O tipo &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;(Mutex Kind)&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;. Os mutex poden ser &amp;quot;&amp;#039;&amp;#039;&amp;#039;fast&amp;#039;&amp;#039;&amp;#039;&amp;quot;, &amp;quot;&amp;#039;&amp;#039;&amp;#039;recursive&amp;#039;&amp;#039;&amp;#039;&amp;quot; ou &amp;quot;&amp;#039;&amp;#039;&amp;#039;error checking&amp;#039;&amp;#039;&amp;#039;&amp;quot; , indicando cando o &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; pode ser volto a ocupar por un thread que o ten xa ocupado (&amp;#039;&amp;#039;recursive&amp;#039;&amp;#039;). O tipo &amp;#039;&amp;#039;error checking&amp;#039;&amp;#039; verifica que o thread que quita o bloqueo sexa o mesmo que o puxo; nos outros tipos un thread pode quitar o bloqueo posto por un thread distinto. Por defecto o tipo é &amp;quot;&amp;#039;&amp;#039;&amp;#039;fast&amp;#039;&amp;#039;&amp;#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
As variables de tipo &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_mutex_t&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; poden ser inicializadas tamén de forma estática mediante as constantes &amp;#039;&amp;#039;&amp;#039;PTHREAD_MUTEX_INITIALIZER&amp;#039;&amp;#039;&amp;#039; (fast mutex), &amp;#039;&amp;#039;&amp;#039;PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP&amp;#039;&amp;#039;&amp;#039; (recursive mutex) e &amp;#039;&amp;#039;&amp;#039;PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP&amp;#039;&amp;#039;&amp;#039; (error checking mutex).&lt;br /&gt;
&lt;br /&gt;
A función &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_mutex_lock&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; ocupa o &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; indicado como parámetro. Si o &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; non está ocupado por outro thread, o ocupa e a continúa a execución, si o &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; xa o ten ocupado outro thread, suspende a execución do thread ata que estea dispoñible. &lt;br /&gt;
&lt;br /&gt;
Si o &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; xa está ocupado polo thread que intenta facer un novo &amp;#039;&amp;#039;pthread_mutex_lock&amp;#039;&amp;#039;, o comportamento depende do tipo de mutex. Si é &amp;#039;&amp;#039;fast&amp;#039;&amp;#039;, o thread queda a espera de que o mutex sexa liberado, o que producirá un &amp;#039;&amp;#039;dead lock&amp;#039;&amp;#039; (bloqueo indefinido); si é &amp;#039;&amp;#039;error checking&amp;#039;&amp;#039; a función devolverá o código de erro &amp;#039;&amp;#039;&amp;#039;EDEADLK&amp;#039;&amp;#039;&amp;#039; e si é &amp;#039;&amp;#039;recursive&amp;#039;&amp;#039;, o thread reocupa o mutex devolvendo o número de veces que o ten ocupado; para liberar o mutex será necesario facer o mesmo número de chamadas a &amp;#039;&amp;#039;&amp;#039;pthread_mutex_unlock&amp;#039;&amp;#039;&amp;#039; que veces se teña ocupado.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_mutex_trylock&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; é igual que &amp;#039;&amp;#039;pthread_mutex_lock&amp;#039;&amp;#039;, pero non bloquea o thread si o mutex está ocupado por outro, se non que devolve o código de erro &amp;#039;&amp;#039;&amp;#039;EBUSY&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_mutex_unlock&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; &amp;quot;libera&amp;quot; o mutex ocupado polo thread. Si o mutex é &amp;#039;&amp;#039;fast&amp;#039;&amp;#039; , sempre se liberará pero si é &amp;#039;&amp;#039;recursive&amp;#039;&amp;#039; decrementará a conta de ocupación do mutex, liberándoo si é 0. No tipo &amp;#039;&amp;#039;error_check&amp;#039;&amp;#039; se verifica que o mutex pertence realmente o thread que intenta liberalo, e si non é así devolve un código de erro, os outros tipos permiten liberar mutex que non lles pertencen, sendo esta unha característica non portable e que non se debe utilizar (en realidade é un [[gal:bug|bug]]).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_mutex_destroy&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; destrúe un obxecto &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; liberando todos os recursos que teña ocupados. Únicamente se poderán destruir mutex que non estean ocupados por ningún thread. (Como en Linux os mutex non ocupan recursos, esta función en realidade non fai nada).&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
int pthread_mutexattr_init(pthread_mutexattr_t *attr);&lt;br /&gt;
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);&lt;br /&gt;
int pthread_mutexattr_settype(pthread_mutexattr_t  *attr,int kind);&lt;br /&gt;
int pthread_mutexattr_gettype(const   pthread_mutexattr_t *attr, int *kind);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_mutexattr_init&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; inicializa o obxecto &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; attr e o inicializa cos valores por defecto.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_mutexattr_destroy&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; destrúe un obxecto que ten atributos de un mutex. En Linux esta función non ten ningún efecto.&lt;br /&gt;
*&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_mutexattr_settype&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; e &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_mutexattr_gettype&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; sirven pra poñer e pra obter o tipo de &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
Os atributos poden ser &amp;#039;&amp;#039;&amp;#039;PTHREAD_MUTEX_FAST_NP&amp;#039;&amp;#039;&amp;#039;, &amp;#039;&amp;#039;&amp;#039;PTHREAD_MUTEX_RECURSIVE_NP&amp;#039;&amp;#039;&amp;#039; ou &amp;#039;&amp;#039;&amp;#039;PTHREAD_MUTEX_ERRORCHECK_NP&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
==== Semáforos ====&lt;br /&gt;
&lt;br /&gt;
Outro mecanismo que poden utilizar os threads pra protexer seccións de código son os &amp;#039;&amp;#039;&amp;#039;semáforos&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
Un &amp;#039;&amp;#039;&amp;#039;semáforo&amp;#039;&amp;#039;&amp;#039; é similar a un &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; cun contador. As operacións principais son:&lt;br /&gt;
*&amp;#039;&amp;#039;esperar a que o contador sexa distinto de 0 e restar 1 o contador antes de continuar&amp;#039;&amp;#039; &lt;br /&gt;
*&amp;#039;&amp;#039;sumar 1 o contador&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Si o contador é 0 indicará que o thread non pode acceder a sección crítica, e si é &amp;gt;0, poderán acceder tantos threads como valor teña o contador. As funcións de manexo de semáforos son:&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
#include &amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int sem_init(sem_t *sem, int pshared, unsigned int value);&lt;br /&gt;
int sem_wait(sem_t *sem);&lt;br /&gt;
int sem_trywait(sem_t *sem);&lt;br /&gt;
int sem_post(sem_t *sem);&lt;br /&gt;
int sem_getvalue(sem_t *sem,int *sval);&lt;br /&gt;
int sem_destroy(sem_t *sem);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;sem_init&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; inicializa o semáforo &amp;#039;&amp;#039;sem&amp;#039;&amp;#039;, poñendo a súa conta inicial a &amp;#039;&amp;#039;value&amp;#039;&amp;#039;. O argumento &amp;#039;&amp;#039;pshared&amp;#039;&amp;#039; indica cando o semáforo é local ó proceso actual (0) ou compartido entre varios procesos (distionto de 0). Linux únicamente soporta semáforos locais ó proceso actual (&amp;#039;&amp;#039;pshared&amp;#039;&amp;#039; debe ser igual a 0).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;sem_wait&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; suspende a execución do thread mentras a conta do semáforo sexa 0. Cando a conta deixe de ser 0, restarálle 1 e continuará a execución.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;sem_trywait&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; é similar a &amp;#039;&amp;#039;sem_wait&amp;#039;&amp;#039; pero en lugar de suspender a execución devolverá o erro &amp;#039;&amp;#039;&amp;#039;EAGAIN&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;sem_post&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; incrementará a conta do semáforo que se lle indique.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;sem_getvalue&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; devolverá a conta do semáforo &amp;#039;&amp;#039;sem&amp;#039;&amp;#039; en &amp;#039;&amp;#039;sval&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;sem_destroy&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; elimina o semáforo que se lle indique.&lt;br /&gt;
&lt;br /&gt;
==== Condicións de Sincronización ====&lt;br /&gt;
&lt;br /&gt;
Unha &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Condición de Sincronización&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; permite suspender a execución de un thread menstras algúns datos compartidos entre varios threads non cumpran un requisito. &lt;br /&gt;
&lt;br /&gt;
As operacións básicas nas &amp;#039;&amp;#039;&amp;#039;condicíóns de sincronización&amp;#039;&amp;#039;&amp;#039; son: &amp;#039;&amp;#039;Sinalizar unha Condición (indicar que o requisito se cumpre)&amp;#039;&amp;#039;, e &amp;#039;&amp;#039;Esperar pola Condición (esperar a que outro thread sinalice a condición )&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
Unha &amp;#039;&amp;#039;condición de sincronización&amp;#039;&amp;#039; sempre está asociada cun &amp;#039;&amp;#039;&amp;#039;mutex&amp;#039;&amp;#039;&amp;#039; pra evitar a &amp;#039;&amp;#039;&amp;#039;condición de competencia&amp;#039;&amp;#039;&amp;#039; que se produce si un thread vai a esperar por unha condición xusto ó mesmo tempo que outro thread a sinaliza, sin darlle a tempo de esperar por ela.&lt;br /&gt;
&lt;br /&gt;
As funcións de manexo de condicións de sincronización son as seguintes:&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;&lt;br /&gt;
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);&lt;br /&gt;
int pthread_cond_signal(pthread_cond_t *cond);&lt;br /&gt;
int pthread_cond_broadcast(pthread_cond_t *cond);&lt;br /&gt;
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);&lt;br /&gt;
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, &lt;br /&gt;
                           const struct timespec *abstime);&lt;br /&gt;
int pthread_cond_destroy(pthread_cond_t *cond);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_cond_init&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; inicializa a variable de condición &amp;#039;&amp;#039;cond&amp;#039;&amp;#039; usando os atributos especificados no parámetro &amp;#039;&amp;#039;cond_attr&amp;#039;&amp;#039;, ou os atributos por defecto si o parámetro é NULL. A implementación en Linux dos threads non soporta atributos para as condicións, de xeito que &amp;#039;&amp;#039;cond_attr&amp;#039;&amp;#039; é sempre ignorado. As variables de tipo &amp;#039;&amp;#039;pthread_cond_t&amp;#039;&amp;#039; tamén poden ser inicializadas estáticamente mediante a constante &amp;#039;&amp;#039;&amp;#039;PTHREAD_COND_INITIALIZER&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_cond_signal&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; fai que continúe &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;ún&amp;#039;&amp;#039;&amp;#039; dos threads que están a espera da variable que se lle pasa como parámetro&amp;#039;&amp;#039;, pero non se sabe cal (pode ser calquera dos que están en espera pra esa condición).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_cond_broadcast&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; fai que continúen &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;todos&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; os threads que estan a esperar pola condición especificada como parámetro.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_cond_wait&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; desbloquea o &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; e suspende o thread á espera de que se cumpla a condición indicada &amp;#039;&amp;#039;(cond)&amp;#039;&amp;#039;. Antes de chamar a esta función é necesario bloquea-lo &amp;#039;&amp;#039;&amp;#039;mutex&amp;#039;&amp;#039;&amp;#039; chamando á función &amp;#039;&amp;#039;&amp;#039;pthread_mutex_lock&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
Antes de voltar, esta función volve a bloquea-lo mutex de xeito automático. Para evitar a &amp;#039;&amp;#039;condición de competencia&amp;#039;&amp;#039; xa comentada, o thread que sinalice a condición con &amp;#039;&amp;#039;pthread_cond_signal&amp;#039;&amp;#039; debe bloquea-lo mutex antes.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_cond_timedwait&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; traballa do mesmo xeito que &amp;#039;&amp;#039;pthread_cond_wait&amp;#039;&amp;#039;, pero su a condición non se cumple no tempo indicado no parámetro &amp;#039;&amp;#039;abstime&amp;#039;&amp;#039;, a función devolve o erro &amp;#039;&amp;#039;&amp;#039;ETIMEDOUT&amp;#039;&amp;#039;&amp;#039;. O tempo ven expresado no formato da función &amp;#039;&amp;#039;time&amp;#039;&amp;#039; (número de segundos dende o 1 de xaneiro de 1970).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_cond_destroy&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; libera unha variable de condición e todos os recursos que poida ter asociados. Na implementación de Linux non ten ningún efecto.&lt;br /&gt;
&lt;br /&gt;
Tanto a función &amp;#039;&amp;#039;pthread_cond_wait&amp;#039;&amp;#039; como &amp;#039;&amp;#039;pthread_cond_timedwait&amp;#039;&amp;#039; son &amp;#039;&amp;#039;&amp;#039;&amp;#039;puntos de cancelación&amp;#039;&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
Vexamos un caso práctico:&lt;br /&gt;
&lt;br /&gt;
Consideremos dúas variables compartidas &amp;#039;&amp;#039;&amp;#039;x&amp;#039;&amp;#039;&amp;#039; e &amp;#039;&amp;#039;&amp;#039;y&amp;#039;&amp;#039;&amp;#039; protexidas polo mutex &amp;#039;&amp;#039;&amp;#039;mut&amp;#039;&amp;#039;&amp;#039; e a condición &amp;#039;&amp;#039;&amp;#039;cond&amp;#039;&amp;#039;&amp;#039; que será sinalizada cando x sexa maior que y:&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
int x,y;&lt;br /&gt;
&lt;br /&gt;
pthread_mutex_t mut=PTHREAD_MUTEX_INITIALIZER;&lt;br /&gt;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Os threads que esperan, incluirán o seguinte código:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
// Bloqueo a sección crítica&lt;br /&gt;
pthread_mutex_lock (&amp;amp;mut);&lt;br /&gt;
// En realidade bastaría un if, pero si hai varios threads...&lt;br /&gt;
while(x&amp;lt;=y) &lt;br /&gt;
{&lt;br /&gt;
  // Esperamos o sinal..&lt;br /&gt;
  pthread_cond_wait(&amp;amp;cond,&amp;amp;mut);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Aquí traballaríamos con &amp;#039;&amp;#039;&amp;#039;x&amp;#039;&amp;#039;&amp;#039; e con &amp;#039;&amp;#039;&amp;#039;y&amp;#039;&amp;#039;&amp;#039; */&lt;br /&gt;
&lt;br /&gt;
// Os outros threads poden continuar...&lt;br /&gt;
pthread_mutex_unlock(&amp;amp;mut);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
O thread que sinaliza a condición tería o código seguinte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
// Bloqueo a sección crítica&lt;br /&gt;
pthread_mutex_lock(&amp;amp;mut);&lt;br /&gt;
&lt;br /&gt;
/* Aquí traballaríamos con &amp;#039;&amp;#039;&amp;#039;x&amp;#039;&amp;#039;&amp;#039; e con &amp;#039;&amp;#039;&amp;#039;y&amp;#039;&amp;#039;&amp;#039; */&lt;br /&gt;
&lt;br /&gt;
// Sinalo a condición. Se únicamente tivera 1 thread en espera bastaría pthread_cond_signal&lt;br /&gt;
if (x&amp;gt;y) pthread_cond_broadcast(&amp;amp;cond);&lt;br /&gt;
// Libero o mutex&lt;br /&gt;
pthread_mutex_unlock(&amp;amp;mut);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Se quixeramos que a espera tivera un &amp;#039;&amp;#039;timeout&amp;#039;&amp;#039; de 5 segundos:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
struct timeval now;&lt;br /&gt;
struct timespec timeout;&lt;br /&gt;
int retcode;&lt;br /&gt;
&lt;br /&gt;
pthread_mutex_lock(&amp;amp;mut);&lt;br /&gt;
gettimeofday(&amp;amp;now);&lt;br /&gt;
timeout.tv_sec=now.tv_sec+5;&lt;br /&gt;
timeout.tv_nsec=now.tv_usec*1000;&lt;br /&gt;
retcode=0;&lt;br /&gt;
while ((x&amp;lt;=y) &amp;amp;&amp;amp; (retcode != ETIMEDOUT)) &lt;br /&gt;
{&lt;br /&gt;
  retcode=pthread_cond_timedwait(&amp;amp;cond,&amp;amp;mut,&amp;amp;timeout);&lt;br /&gt;
}&lt;br /&gt;
if (retcode == ETIMEDOUT) &lt;br /&gt;
{&lt;br /&gt;
  /* Error, acabouse o tempo (pasaron os 5 segundos) */&lt;br /&gt;
} else &lt;br /&gt;
{&lt;br /&gt;
  /* Traballar coas variables &amp;#039;&amp;#039;&amp;#039;x&amp;#039;&amp;#039;&amp;#039; e &amp;#039;&amp;#039;&amp;#039;y&amp;#039;&amp;#039;&amp;#039; */&lt;br /&gt;
}&lt;br /&gt;
pthread_mutex_unlock(&amp;amp;mut);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cancelación de Threads ===&lt;br /&gt;
&lt;br /&gt;
A cancelación é un mecanismo polo que un thread pode provocar a finalización de outro enviándolle unha petición de finalización. Dependendo do xeito de traballar do outro thread, pode ignora-la petición, finalizar inmediatamente ou esperar a alcanzar un &amp;#039;&amp;#039;punto de cancelación&amp;#039;&amp;#039;. Si o thread atende inmediatamente a petición remata devolvendo o código &amp;#039;&amp;#039;&amp;#039;PTHREAD_CANCELED&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
Os &amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;puntos de cancelación&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; son puntos na execución donde se comproba si hai peticións de cancelación pendentes. As seguintes funcións teñen puntos de cancelación: &amp;#039;&amp;#039;&amp;#039;pthread_join&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;pthread_cond_wait&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;pthread_cond_timedwait&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;pthread_testcancel&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;sem_wait&amp;#039;&amp;#039;&amp;#039; &amp;#039;&amp;#039;&amp;#039;sigwait&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
As funcions de cancelación de thread son as seguintes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
int pthread_cancel(pthread_t thread);&lt;br /&gt;
int pthread_setcancelstate(int state, int *oldstate);&lt;br /&gt;
int  pthread_setcanceltype(int type,int *oldtype);&lt;br /&gt;
int  pthread_testcancel(void);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_cancel&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; envía unha petición de cancelación ó thread indicado como argumento.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_setcancelstate&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; cambia o estado de cancelación do thread, é decir indica cando se ignorarán as sinais de cancelación e cando non. O parámetro &amp;#039;&amp;#039;state&amp;#039;&amp;#039; pode ser &amp;#039;&amp;#039;&amp;#039;PTHREAD_CANCEL_ENABLE&amp;#039;&amp;#039;&amp;#039; pra permitir a cancelación ou &amp;#039;&amp;#039;&amp;#039;PTHREAD_CANCEL_DISABLE&amp;#039;&amp;#039;&amp;#039; pra non permitila. Si o parámetro &amp;#039;&amp;#039;oldstate&amp;#039;&amp;#039; non é NULL, devolverá o estado de cancelación previo.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_setcanceltype&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; cambia o tipo de resposta ás peticións de cancelación, e pode ser &amp;#039;&amp;#039;&amp;#039;PTHREAD_CANCEL_ASYNCHRONOUS&amp;#039;&amp;#039;&amp;#039; (pra cancelación inmediata) ou &amp;#039;&amp;#039;&amp;#039;PTHREAD_CANCEL_DEFERRED&amp;#039;&amp;#039;&amp;#039; (esperar ó seguinte punto de cancelación). Si o parámetro &amp;#039;&amp;#039;oldtype&amp;#039;&amp;#039; non é NULL almacenará o tipo de cancelación anterior.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_testcancel&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; únicamente sitúa un punto de cancelación no lugar en que se chame.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Os threads créanse por defecto coa cancelación activa co tipo PTHREAD_CANCEL_DEFERRED&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== Envío e Xestión de Sinais. ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
int pthread_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask);&lt;br /&gt;
int pthread_kill(pthread_t thread, int signo);&lt;br /&gt;
int sigwait(const sigset_t *set, int *sig);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_sigmask&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; cambia o conxunto de sinais o que vai a respostar o thread. Si o parámetro &amp;#039;&amp;#039;oldmask&amp;#039;&amp;#039; non é NULL, almacenará o conxunto vello de sinais. Si &amp;#039;&amp;#039;how&amp;#039;&amp;#039; é &amp;#039;&amp;#039;&amp;#039;SIG_SETMASK&amp;#039;&amp;#039;&amp;#039; o conxunto de sinais se inicializa a &amp;#039;&amp;#039;newmask&amp;#039;&amp;#039;, si é &amp;#039;&amp;#039;&amp;#039;SIG_BLOCK&amp;#039;&amp;#039;&amp;#039; engádense as sinais especificadas en &amp;#039;&amp;#039;newmask&amp;#039;&amp;#039; e si é &amp;#039;&amp;#039;&amp;#039;SIG_UNBLOCK&amp;#039;&amp;#039;&amp;#039; quítanse as sinais especificadas en &amp;#039;&amp;#039;newmask&amp;#039;&amp;#039; do conxunto de sinais ós que vai respostar o thread. Os conxuntos de sinais manipúlanse coas funcións:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
int sigemptyset(sigset_t *conxunto); // (vacía o conxunto de sinais indicado).&lt;br /&gt;
int sigfillset(sigset_t *conxunto);  // (inclúe todos os sinais existentes no conxunto indicado).&lt;br /&gt;
int sigaddset(sigset_t *conxunto, int numsinal); // (engade o sinal indicado ó conxunto).&lt;br /&gt;
int sigdelset(sigset_t *conxunto, int numsinal); // (elimina o sinal indicado do conxunto).&lt;br /&gt;
int sigismember(const sigset_t *conxunto, int numsinal); // (indica si o sinal indicado pertence o conxunto).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;pthread_kill&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; envía o sinal &amp;#039;&amp;#039;signo&amp;#039;&amp;#039; o thread especificado.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;sigwait&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039; suspende o thread hasta que recibe unha sinal do conxunto indicado en &amp;#039;&amp;#039;set&amp;#039;&amp;#039;, almacenando entonces o sinal recibido en &amp;#039;&amp;#039;sig&amp;#039;&amp;#039;. Se ignorará calqueira función asociada o sinal.&lt;br /&gt;
&lt;br /&gt;
=== Exemplos ===&lt;br /&gt;
==== Creación dun Thread ====&lt;br /&gt;
&lt;br /&gt;
Este programa crea dous fíos de execución que visualizan o mesmo tempo os números dende 0 a 1000000000. Pra distinguir o primeiro thread visualizará &amp;#039;&amp;#039;&amp;#039;THREAD PPAL: &amp;lt;nº&amp;gt;&amp;#039;&amp;#039;&amp;#039; e o thread que lanzamos visualizará &amp;#039;&amp;#039;&amp;#039;THREAD 1: &amp;lt;nº&amp;gt;&amp;#039;&amp;#039;&amp;#039;: &lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void *funcion(void *arg);&lt;br /&gt;
&lt;br /&gt;
// Función que vai a ser executada como un thread secundario.&lt;br /&gt;
// Visualiza números entre 0 e 1000000000&lt;br /&gt;
//&lt;br /&gt;
void *funcion(void *arg) &lt;br /&gt;
{&lt;br /&gt;
  unsigned int x;&lt;br /&gt;
&lt;br /&gt;
  x=0;&lt;br /&gt;
  while(x&amp;lt;=1000000000) &lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;THREAD 1: %d\n&amp;quot;,x);&lt;br /&gt;
    x++;&lt;br /&gt;
  }&lt;br /&gt;
  return NULL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Programa Principal. Visualizará números entre 0 e 1000000000&lt;br /&gt;
// despois de lanzar outro thread de execución.&lt;br /&gt;
void  main(void)  &lt;br /&gt;
{&lt;br /&gt;
  // Variable para almacenar a información do thread creado.&lt;br /&gt;
  // O thread principal é a función main().&lt;br /&gt;
  pthread_t thr;&lt;br /&gt;
&lt;br /&gt;
  // Variable pra almacenar o valor devolto polo thread executado.&lt;br /&gt;
  void *retval;&lt;br /&gt;
  &lt;br /&gt;
  unsigned int x;&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
  // Creación do novo thread.&lt;br /&gt;
  pthread_create(&amp;amp;thr,NULL,funcion,NULL);&lt;br /&gt;
  // A partir deste momento, &amp;#039;funcion&amp;#039; executarase ó mesmo tempo.&lt;br /&gt;
  // que o seguinte código....&lt;br /&gt;
  x=0;&lt;br /&gt;
  while(x&amp;lt;=1000000000) &lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;THREAD PPAL: %d\n&amp;quot;,x);&lt;br /&gt;
    x++;&lt;br /&gt;
  }&lt;br /&gt;
  // Esperamos a que finalice o thread secundario.&lt;br /&gt;
  // (lanzado dende esta función).&lt;br /&gt;
  pthread_join(thr,&amp;amp;retval);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sincronización con Mutex ====&lt;br /&gt;
Este programa crea dous fíos de execución que visualizan o mesmo tempo os números dende 0 a 1000000000. Para distinguir o primeiro thread visualizará &amp;#039;&amp;#039;&amp;#039;THREAD PPAL: &amp;lt;nº&amp;gt;&amp;#039;&amp;#039;&amp;#039; e o thread que lanzamos visualizará &amp;#039;&amp;#039;&amp;#039;THREAD 1: &amp;lt;nº&amp;gt;&amp;#039;&amp;#039;&amp;#039;. Utilizaremos un &amp;#039;&amp;#039;mutex&amp;#039;&amp;#039; pra facer que primeiro faga toda a conta un thread e logo o outra:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void *funcion(void *arg);&lt;br /&gt;
&lt;br /&gt;
// Variable mutex pra facer que un thread espere a que finalice o outro.&lt;br /&gt;
// utilizaremos un mutex &amp;#039;fast&amp;#039;.&lt;br /&gt;
pthread_mutex_t   semaforo=PTHREAD_MUTEX_INITIALIZER;&lt;br /&gt;
&lt;br /&gt;
void *funcion(void *arg) &lt;br /&gt;
{&lt;br /&gt;
  unsigned int x;&lt;br /&gt;
&lt;br /&gt;
  // Ocupamos o mutex (si non está ocupado).&lt;br /&gt;
  pthread_mutex_lock(&amp;amp;semaforo);&lt;br /&gt;
  &lt;br /&gt;
  x=0;&lt;br /&gt;
  while(x&amp;lt;=1000000000) &lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;THREAD 1: %d\n&amp;quot;,x);&lt;br /&gt;
    x++;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Liberamos o mutex.&lt;br /&gt;
  pthread_mutex_unlock(&amp;amp;semaforo);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void  main(void)  &lt;br /&gt;
{&lt;br /&gt;
  // Variable pra almacenar a información do thread creado. .&lt;br /&gt;
  // O thread principal será a función main().&lt;br /&gt;
  pthread_t thr;&lt;br /&gt;
  // Variable pra almacenar o valor devolto polo thread executado.&lt;br /&gt;
  void *retval;&lt;br /&gt;
  unsigned int x;&lt;br /&gt;
&lt;br /&gt;
  // Creación do novo thread.&lt;br /&gt;
  pthread_create(&amp;amp;thr,NULL,funcion,NULL);&lt;br /&gt;
&lt;br /&gt;
  // A partir deste momento, &amp;#039;funcion&amp;#039; executarase simultáneamente.&lt;br /&gt;
  // Ocupamos o mutex (si non está ocupado).&lt;br /&gt;
  pthread_mutex_lock(&amp;amp;semaforo);&lt;br /&gt;
  x=0;&lt;br /&gt;
  while(x&amp;lt;=1000000000) &lt;br /&gt;
  {&lt;br /&gt;
    printf(&amp;quot;THREAD PPAL: %d\n&amp;quot;,x);&lt;br /&gt;
    x++;&lt;br /&gt;
  }&lt;br /&gt;
  // Liberamos o mutex.&lt;br /&gt;
  pthread_mutex_unlock(&amp;amp;semaforo);&lt;br /&gt;
  // Esperamos a que finalice o thread secundario.&lt;br /&gt;
  // (lanzado dende esta función).&lt;br /&gt;
  pthread_join(thr,&amp;amp;retval);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==== Sincronización con Semáforos ====&lt;br /&gt;
Este programa crea dous fíos de execución que mercan entradas mentras quedan. Para distinguir o primeiro thread visualizará &amp;#039;&amp;#039;&amp;#039;THREAD 1:&amp;#039;&amp;#039;&amp;#039; e o segundo thread &amp;#039;&amp;#039;&amp;#039;THREAD 2: &amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;#039;C&amp;#039;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int __numEntradas=100000;&lt;br /&gt;
&lt;br /&gt;
sem_t semaforo;&lt;br /&gt;
&lt;br /&gt;
void *funcion(void *arg);&lt;br /&gt;
 &lt;br /&gt;
// Función que vai a ser executada como un thread secundario.&lt;br /&gt;
// Visualiza números entre 0 e 1000000000&lt;br /&gt;
//&lt;br /&gt;
void *funcion(void *arg) &lt;br /&gt;
{&lt;br /&gt;
   while(__numEntradas&amp;gt;0) {&lt;br /&gt;
     sem_wait(&amp;amp;semaforo); &lt;br /&gt;
     if (__numEntradas&amp;gt;0) {  &lt;br /&gt;
       printf(&amp;quot;%s MERCA ENTRADA %d\n&amp;quot;,arg,__numEntradas);&lt;br /&gt;
       __numEntradas--;&lt;br /&gt;
     }&lt;br /&gt;
     sem_post(&amp;amp;semaforo);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
// Programa Principal. Visualizará números entre 0 e 1000000000&lt;br /&gt;
// despois de lanzar outro thread de execución.&lt;br /&gt;
void  main(void)  &lt;br /&gt;
{&lt;br /&gt;
  // Variable para almacenar a información do thread creado.&lt;br /&gt;
  // O thread principal é a función main().&lt;br /&gt;
  pthread_t thr,thr1;&lt;br /&gt;
 &lt;br /&gt;
  // Variable pra almacenar o valor devolto polo thread executado.&lt;br /&gt;
  void *retval;&lt;br /&gt;
  &lt;br /&gt;
  sem_init(&amp;amp;semaforo,0,1);&lt;br /&gt;
&lt;br /&gt;
  // Creación do novo thread.&lt;br /&gt;
  pthread_create(&amp;amp;thr,NULL,funcion,&amp;quot;THREAD 1&amp;quot;);&lt;br /&gt;
  pthread_create(&amp;amp;thr1,NULL,funcion,&amp;quot;THREAD 2&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Esperamos a que finalice o thread secundario.&lt;br /&gt;
  // (lanzado dende esta función).&lt;br /&gt;
  pthread_join(thr,&amp;amp;retval);&lt;br /&gt;
  pthread_join(thr1,&amp;amp;retval);&lt;br /&gt;
  printf(&amp;quot;Quedan %d\n&amp;quot;,__numEntradas);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Xavi</name></author>
	</entry>
</feed>