1: differences between threads and processes
2: thread synchronization: mutex lock
3: thread synchronization: Condition variable
4. Thread Synchronization: The post semaphore has an instance in the code. 5: The thread exits.
6: Sample thread code
/* ===================================================== ============================================================ Name: threaddemo. c Author: Version: Copyright: Your copyright notice Description: Hello world in C, ANSI-style ========================================== ======================================================= * /# include <syslog. h> # include <pthread. h> # include <sys/types. h> # include <sys/MSG. h> # include <sys/STAT. h> # include <stddef. h>/* F Or definition of offsetof () */# include <stdarg. h>/* for definition of offsetof () */# include <limits. h> # include <fcntl. h> # include <signal. h> # include <sys/Wait. h> # include <sys/types. h>/* type definitions used by using programs */# include <stdio. h>/* standard I/O functions */# include <stdlib. h>/* prototypes of commonly used library functions, plus exit_success and exit_failure constants */# include <Unistd. h>/* prototypes for each system cballs */# include <errno. h>/* declares errno and defines error constants */# include <string. h>/* commonly used string-handling functions */# include <sys/Param. h> # include <pthread. h> # include <semaphore. h> typedef Enum {false, true} Boolean;/* One of the reasons for using multithreading is that it is a very "frugal" multi-task operation compared with the process. We know that in a Linux system, starting a new process must be allocated to it with an independent address space, creating a large number of data tables to maintain its code segment, stack segment, and data segment, this is an "expensive" way of multitasking. While multiple threads running in a process use the same address space for each other to share most of the data. The space required to start a thread is much less than the space required to start a process, in addition, the time required for switching between threads is much less than the time required for switching between processes. According to statistics, the overhead of a process is about 30 times the overhead of a thread. Of course, in a specific system, this data may be significantly different */struct menber {int A; char * s ;}; void cleanup (void * Arg) {printf ("cleanup Arg: % s \ n ", ARG);} void * thread_one (void * Arg) {pid_t PID; pthread_t tid; pid = getpid (); tid = pthread_self (); struct menber * parameter = (struct menber *) ARG; pthread_cleanup_push (cleanup, (void *) parameter-> S); // atexit (); printf ("thread_one: the PID is % u, the thread is % u \ n ", PID, tid ); Printf ("A: % d S: % s \ n", parameter-> A, parameter-> S); pthread_cleanup_pop (1); // pthread_cleanup_pop (0 ); // atexit (); pthread_exit (void *) parameter-> A);} void * thread_two (void * Arg) {pid_t PID; pthread_t tid; pid = getpid (); tid = pthread_self (); printf ("thread_two: The PID is % u, the thread is % u \ n", PID, tid); Return (void *) 8 ;} void pthreadparamter () {int err, stat_val; pid_t PID, childpid; pthread_t tid_one, tid_two; Pi D = getpid (); tid_one = pthread_self (); void * retvalue_one, * retvalue_two; struct menber parameter; parameter. A = 123456; parameter. S = "Suiyuan"; if (childpid = fork () =-1) {perror ("fork"); exit (exit_failure );} else if (childpid = 0) {err = pthread_create (& tid_one, null, thread_one, (void *) ¶ meter); If (Err! = 0) {printf ("error message is: % s \ n", strerror (ERR); exit (1) ;}pthread_join (tid_one, & retvalue_one ); printf ("pthread_join, thread_one return value: % d \ n", (INT) retvalue_one);} else {pthread_create (& tid_two, null, (void *) thread_two, null ); if (Err! = 0) {printf ("error message is: % s \ n", strerror (ERR); exit (1) ;} pthread_join (tid_two, & retvalue_two ); printf ("pthread_join, thread_two return value: % d \ n", (INT) retvalue_two); printf ("PID: % d getpid: % d \ n", PID, getpid (); waitpid (childpid, & stat_val, 0); If (wifexited (stat_val) {printf ("Child exited with code % d \ n ", wexitstatus (stat_val);} else if (wifsignaled (stat_val) {printf ("Child terminated abnormally, signal % D \ n ", wtermsig (stat_val) ;}} printf (" main thread: The PID is % u, the thread is % u \ n ", PID, tid_one);}/* If any thread in the process calls exit, _ exit, or _ exit, the whole process will be terminated. Similarly, if the default signal action is to terminate the process, sending the signal to the thread will terminate the process. Method of normal thread Exit: (1) the thread returns only from the startup routine, and the return value is the exit code in the thread (2) the thread can be terminated by another process (3) the thread calls the pthread_exit function *///******************************* **************************************** * *********************** # If 1 static pthread_mutex_t DIV = pthread_mutex_initializer; static pthread_cond_t cond = pthread_cond_initializer; # endif # If 1 static int avail = 0; static void * pthread_mutex_lock_func (void * Arg) {int CNT = * (int *) ARG ); Int S, J; printf ("pthread_mutex_lock_func: Arg: % d \ n", CNT); sleep (1); For (j = 0; j <CNT; j ++) {sleep (2);/* code to produce a unit omitted */S = pthread_mutex_lock (& CTX); If (s! = 0) perror ("pthread_mutex_lock"); Avail ++;/* Let consumer know another unit is available */S = pthread_mutex_unlock (& CTX); If (s! = 0) perror ("pthread_mutex_unlock"); # If 1 S = pthread_cond_signal (& Cond);/* wake Sleeping consumer */If (s! = 0) perror ("pthread_cond_signal"); # endif} return NULL;} void pthread_mutex_lock_test (INT num) {pthread_t tid; int s; int totrequired; /* Total Number of units that all threads will produce */INT numconsumed;/* Total units so far consumed */Boolean done; time_t t; t = time (null ); /* create all threads */{totrequired = num; printf ("totrequired: % d \ n", totrequired); s = pthread_create (& tid, null, Pthread_mutex_lock_func, (void *) & totrequired); If (s! = 0) perror ("pthread_create");}/* use a polling loop to check for available units */numconsumed = 0; done = false; (;;) {S = pthread_mutex_lock (& CTX); If (s! = 0) {perror ("pthread_mutex_lock");} // while (avail = 0) {/* wait for something to consume */S = pthread_cond_wait (& cond, & mt); If (s! = 0) perror ("pthread_cond_wait");} // while (avail> 0) {/* consume all available units * // * Do something with Produced Unit */numconsumed ++; printf ("condition is ture; t = % ld: avail = % d numconsumed = % d \ n ", (long) (Time (null)-T), avail, numconsumed); avail --; done = numconsumed> = totrequired ;} S = pthread_mutex_unlock (& CTX); If (s! = 0) {perror ("pthread_mutex_unlock");} If (done) {break ;} /* perhaps do other work here that does not require mutex lock */} exit (exit_success );} # endif //************************************ * ** condition example *********************************** * *********** # If 1/* Static pthread_mutex_t CTX = pthread_mutex_initializer; static pthread_cond_t cond = pthread_cond_initializer; */static int glob = 0; ST Atic void cleanuphandler (void * Arg)/* free memory pointed to by 'arg 'and unlock mutex */{int s; printf ("cleanup: freeing block at % P \ n ", ARG); free (ARG); printf (" cleanup: Unlocking mutex \ n "); s = pthread_mutex_unlock (& CTX ); if (s! = 0) perror ("pthread_mutex_unlock");} static void * mutex_conditionfunc (void * Arg) {int s; void * Buf = NULL; /* buffer allocated by thread */Buf = malloc (0x10000);/* not a cancellation point */printf ("thread: allocated memory at % P \ n ", buf); s = pthread_mutex_lock (& CTX);/* not a cancellation point */If (s! = 0) {perror ("pthread_mutex_lock");} pthread_cleanup_push (cleanuphandler, Buf); // while (glob = 0) {printf ("pthread_cond_wait become to ture \ n"); s = pthread_cond_wait (& cond, & CTX);/* a cancellation point */If (s! = 0) {perror ("pthread_cond_wait") ;}} printf ("thread: Condition wait loop completed \ n"); pthread_cleanup_pop (1 ); /* executes cleanup handler */return NULL;} void mutex_condition_test (INT argc) {pthread_t thr; void * res; int s; S = pthread_create (& Thr, null, mutex_conditionfunc, null); If (s! = 0) {perror ("pthread_create");} printf ("Main: Sleep 5s \ n"); sleep (5 ); /* Give thread a chance to get started */If (argc = 1) {/* cancel thread */printf ("Main: about to cancel thread \ n "); S = pthread_cancel (THR); If (s! = 0) {perror ("pthread_cancel") ;}} else {/* signal condition variable */printf ("Main: About to signal condition variable \ n "); glob = 1; S = pthread_cond_signal (& Cond); If (s! = 0) {perror ("pthread_cond_signal") ;}} S = pthread_join (Thr, & res); If (s! = 0) perror ("pthread_join"); If (RES = pthread_canceled) printf ("Main: thread was canceled \ n"); else printf ("Main: thread terminated normally \ n "); exit (exit_success) ;}# endifstatic int globcount = 0; static sem_t postsem; static void * threadpostsemaphoresfunc (void * Arg) /* loop 'arg 'times incrementing 'glob' */{int loops = * (int *) Arg); int Loc, J; For (j = 0; j <loops; j ++) {If (sem_wait (& Pos Tsem) =-1) perror ("sem_wait"); loc = globcount; loc ++; globcount = LOC; printf ("threadpostsemaphoresfunc: loops % d globcount % d \ n ", loops, globcount); sleep (1); If (sem_post (& postsem) =-1) perror (" sem_post ");} return NULL;} void threadandpostsemaphorestest (INT loops) {pthread_t T1, T2; int S, loops1 = loops + 1; /* initialize a semaphore with the value 1 */If (sem_init (& postsem, 0, 1) =-1) perror ("Sem_init");/* create two threads that increment 'glob' */S = pthread_create (& T1, null, threadpostsemaphoresfunc, & loops1); If (s! = 0) perror ("pthread_create"); s = pthread_create (& T2, null, threadpostsemaphoresfunc, & loops); If (s! = 0) perror ("pthread_create");/* Wait For threads to terminate */S = pthread_join (T1, null); If (s! = 0) perror ("pthread_join"); s = pthread_join (t2, null); If (s! = 0) perror ("pthread_join"); printf ("globcount = % d \ n", globcount); exit (exit_success);} usageerror (const char * progname, const char * MSG) {If (MSG! = NULL) {fprintf (stderr, "% s", MSG);} fprintf (stderr, "Usage: % s [Options] Parameter \ n", progname ); fprintf (stderr, "Usage: % s [Tm: C: P:] Parameter \ n", progname); fprintf (stderr, "Usage: % s-t; To execute: pthreadparamter () \ n ", progname); fprintf (stderr," Usage: % s-M parameter; To execute: pthread_mutex_lock_test () \ n ", progname); fprintf (stderr, "Usage: % s-c [parameter]; To execute: mutex_condition_t Est () \ n ", progname); fprintf (stderr," Usage: % s-p parameter; To execute: threadandpostsemaphorestest () \ n ", progname); fprintf (stderr, "Usage: % s-h; To execute: Help \ n", progname); exit (exit_failure);} int main (INT argc, char * argv []) {int OPT; If (argc = 1) {perror (""); usageerror (argv [0], null) ;}while (OPT = getopt (argc, argv, "TM: C: K: P :"))! =-1) {Switch (OPT) {Case 'T': pthreadparamter (); break; Case 'M': If (optarg! = NULL) {printf ("optopt: % C: % d \ n", optopt, atoi (optarg); pthread_mutex_lock_test (atoi (optarg ));} else {usageerror (argv [0], null);} break; Case 'C': If (optarg! = NULL) {printf ("optopt: % C: % d \ n", optopt, atoi (optarg); mutex_condition_test (atoi (optarg ));} else {usageerror (argv [0], null);} break; case 'p': If (optarg! = NULL) {printf ("optopt: % C: % d \ n", optopt, atoi (optarg); threadandpostsemaphorestest (atoi (optarg ));} else {usageerror (argv [0], null);} break; default: usageerror (argv [0], null) ;}return exit_success ;}7: code execution result