#1 Le 07/07/2008, à 10:27
- volkukan
Aucune concurrence entre mes threads, comprend pas?
Bonjours jvien de m'initier dans la programmation de thread avec la lib pthread et en essayant quelques codes trouvés à droite à gauche, j'en viens à la conclusion qu'a chaque exécution du code je ne vois aucune forme de concurrence entre mes threads, en effet si dans ma fonction principale je creé le thread A puis le thread B, le premier finira toujours en premier et le second en second
exemple : Hello world
#include <stdio.h>
#include <pthread.h>
static void *task_a (void *p_data)
{
puts ("Hello world A");
(void) p_data;
return NULL;
}
static void *task_b (void *p_data)
{
puts ("Hello world B");
(void) p_data;
return NULL;
}
int main (void)
{
pthread_t ta;
pthread_t tb;
puts ("main init");
pthread_create (&ta, NULL, task_a, NULL);
pthread_create (&tb, NULL, task_b, NULL);
puts ("main end");
return 0;
}
Comportement attendue,
main init
main end
Hello world A
Hello world B
et moi c'est toujours ça :
main init
Hello world A
Hello world B
main end
Par la suite j'apprend que pour arriver à mon résultat il faut ajouter à mon code initial des fonctions spéciales pthread_join pour ainsi contrôller la concurence entre les threads. Donc voila, sans les avoirs ajoutées j'arrive à ce résultat d'où mon incompréhension. Si quelqun aurait un code encore plus simple pour vérifier ma théorie je suis preneur.
Dernière modification par volkukan (Le 07/07/2008, à 10:29)
Hors ligne
#2 Le 07/07/2008, à 11:32
- nicolas.sitbon
Re : Aucune concurrence entre mes threads, comprend pas?
Tes fonctions de thread sont trop rapides, essaye comme ça :
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
static void *task_a (void *p_data)
{
sleep (2);
puts ("Hello world A");
(void) p_data;
return NULL;
}
static void *task_b (void *p_data)
{
sleep (1);
puts ("Hello world B");
(void) p_data;
return NULL;
}
int main (void)
{
puts ("main init");
pthread_create (&(pthread_t){0}, NULL, task_a, NULL);
pthread_create (&(pthread_t){0}, NULL, task_b, NULL);
puts ("main end");
pthread_exit(&(int){0});
}
Hors ligne
#3 Le 07/07/2008, à 11:38
- volkukan
Re : Aucune concurrence entre mes threads, comprend pas?
Merci pour ta reponse! en effet sa fonctionne!
Juste une question sur ta façon de programmer, que signifie
&(pthread_t){0} et &(int){0}
je vois pas ça souvent.
merci!
edit : en passant je m'interesse au thread aussi parce que je me demande si il est possible de les utiliser pour eviter des boucle infinie while qui consomme toute mes ressources cpu, y a til une technique qui utiliserait les threads?
Dernière modification par volkukan (Le 07/07/2008, à 11:40)
Hors ligne
#4 Le 07/07/2008, à 12:08
- nicolas.sitbon
Re : Aucune concurrence entre mes threads, comprend pas?
Pour ce qui est de la notation
&(pthread_t){0} et &(int){0}
c'est un ajout de la norme C99 que l'on appelle les littéraux composés ( de l'anglais "compound literals"), ça permet de créer des variables locales anonymes (pratiques quand on a pas besoin du nom).
Pour ton autre question, il faut savoir qu'on distingue en général plusieurs façons de programmer :
- avec des processus (fork)
- avec des threads (pthread_create)
- avec des évênements (poll(), select())
- asynchrone (aio_read() et compagnie)
on peut aussi trouver des mix.
Dans ton cas, le plus judicieux serait les évênements ou les entrées sorties asynchrones.
Hors ligne
#5 Le 07/07/2008, à 12:11
- nicolas.sitbon
Re : Aucune concurrence entre mes threads, comprend pas?
tiré de la norme C99 :
6.5.2.5 Compound literals
Constraints
1 The type name shall specify an object type or an array of unknown size, but not a variable
length array type.
2 No initializer shall attempt to provide a value for an object not contained within the entire
unnamed object specified by the compound literal.
3 If the compound literal occurs outside the body of a function, the initializer list shall
consist of constant expressions.
Semantics
4 A postfix expression that consists of a parenthesized type name followed by a brace-
enclosed list of initializers is a compound literal. It provides an unnamed object whose
value is given by the initializer list.84)
5 If the type name specifies an array of unknown size, the size is determined by the
initializer list as specified in 6.7.8, and the type of the compound literal is that of the
completed array type. Otherwise (when the type name specifies an object type), the type
of the compound literal is that specified by the type name. In either case, the result is an
lvalue.
84) Note that this differs from a cast expression. For example, a cast specifies a conversion to scalar types
or void only, and the result of a cast expression is not an lvalue.
§6.5.2.5 Language 75
ISO/IEC 9899:TC3 Committee Draft — Septermber 7, 2007 WG14/N1256
6 The value of the compound literal is that of an unnamed object initialized by the
initializer list. If the compound literal occurs outside the body of a function, the object
has static storage duration; otherwise, it has automatic storage duration associated with
the enclosing block.
7 All the semantic rules and constraints for initializer lists in 6.7.8 are applicable to
compound literals.85)
8 String literals, and compound literals with const-qualified types, need not designate
distinct objects.86)
EXAMPLE 1 The file scope definition
9
int *p = (int []){2, 4};
initializes p to point to the first element of an array of two ints, the first having the value two and the
second, four. The expressions in this compound literal are required to be constant. The unnamed object
has static storage duration.
EXAMPLE 2 In contrast, in
10
void f(void)
{
int *p;
/*...*/
p = (int [2]){*p};
/*...*/
}
p is assigned the address of the first element of an array of two ints, the first having the value previously
pointed to by p and the second, zero. The expressions in this compound literal need not be constant. The
unnamed object has automatic storage duration.
EXAMPLE 3 Initializers with designations can be combined with compound literals. Structure objects
11
created using compound literals can be passed to functions without depending on member order:
drawline((struct point){.x=1, .y=1},
(struct point){.x=3, .y=4});
Or, if drawline instead expected pointers to struct point:
drawline(&(struct point){.x=1, .y=1},
&(struct point){.x=3, .y=4});
EXAMPLE 4 A read-only compound literal can be specified through constructions like:
12
(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}
85) For example, subobjects without explicit initializers are initialized to zero.
86) This allows implementations to share storage for string literals and constant compound literals with
the same or overlapping representations.
76 Language §6.5.2.5
WG14/N1256 Committee Draft — Septermber 7, 2007 ISO/IEC 9899:TC3
EXAMPLE 5 The following three expressions have different meanings:
13
"/tmp/fileXXXXXX"
(char []){"/tmp/fileXXXXXX"}
(const char []){"/tmp/fileXXXXXX"}
The first always has static storage duration and has type array of char, but need not be modifiable; the last
two have automatic storage duration when they occur within the body of a function, and the first of these
two is modifiable.
EXAMPLE 6 Like string literals, const-qualified compound literals can be placed into read-only memory
14
and can even be shared. For example,
(const char []){"abc"} == "abc"
might yield 1 if the literals’ storage is shared.
EXAMPLE 7 Since compound literals are unnamed, a single compound literal cannot specify a circularly
15
linked object. For example, there is no way to write a self-referential compound literal that could be used
as the function argument in place of the named object endless_zeros below:
struct int_list { int car; struct int_list *cdr; };
struct int_list endless_zeros = {0, &endless_zeros};
eval(endless_zeros);
EXAMPLE 8 Each compound literal creates only a single object in a given scope:
16
struct s { int i; };
int f (void)
{
struct s *p = 0, *q;
int j = 0;
again:
q = p, p = &((struct s){ j++ });
if (j < 2) goto again;
return p == q && q->i == 1;
}
The function f() always returns the value 1.
17 Note that if an iteration statement were used instead of an explicit goto and a labeled statement, the
lifetime of the unnamed object would be the body of the loop only, and on entry next time around p would
have an indeterminate value, which would result in undefined behavior.
Forward references: type names (6.7.6), initialization (6.7.8).
Hors ligne