1, Create a new thread
1. Header file: < pthread h>
2. Function: pthread_create(pthread_t *thread,const pyhread_attr_t *attr,void *(start_routine) (void ),void *arg);
name | significance |
---|---|
pthread_t | Equivalent to unsigned integer length |
*thread | ID of the thread |
const pyhread_attr_t *attr | Half of the properties of the thread are ignored. By default |
void *(start_routine) (void ) | Thread routine is actually equivalent to the entry function of creating thread. It is essentially a callback function |
void *arg | The parameters of the function are passed if any, and are not set to NULL |
3. Execute the new thread, and the main process still continues to execute
makefile file:
mythread:mythread.c gcc -o $@ $^ -lpthread #The pthread library is cited .PHONY:clean clean: rm -f mythread
mythread file:
#include<stdio.h> #include<pthread.h> #include<unistd.h> void *Routine(void *arg) { char *msg = (char*)arg; while(1) { printf("%s\n",msg); sleep(1); } } int main() { pthread_t tid; //Create thread pthread_create(&tid,NULL,Routine,(void*)"thread 1"); //Pass thread 1 parameter while(1) { printf("I am main thread!\n"); sleep(2); } return 0; }
result:
4. Check whether it belongs to a process. Print the id numbers of thread and process respectively. The id numbers of thread and process are consistent
#include<stdio.h> #include<pthread.h> #include<unistd.h> void *Routine(void *arg) { char *msg = (char*)arg; while(1) { printf("%s: pid:%d,ppid:%d\n",msg,getpid(),getppid()); sleep(1); } } int main() { pthread_t tid; //Create thread pthread_create(&tid,NULL,Routine,(void*)"thread 1"); //Pass thread 1 parameter while(1) { printf("main thread:pid:%d,ppid:%d\n",getpid(),getppid()); sleep(2); } return 0; }
5. PS - Al | head - 1 & & PS - Al | grep myThread
-50: Displays the current lightweight process
LWP: lightweight process ID
When OS scheduling is basic, LWP is used instead of PID!
In Linux, the application layer thread is 1:1 with the LWP of the kernel
6. Create a batch of threads
#include<stdio.h> #include<pthread.h> #include<unistd.h> #include<sys/types.h> void *Routine(void *arg) { char *msg = (char*)arg; while(1) { printf("%s: pid:%d,ppid:%d\n",msg,getpid(),getppid()); sleep(1); } } int main() { pthread_t tid[5]; //Create thread for(int i = 0; i < 5; i++) { char buffer[64]; sprintf(buffer,"thread %d",i); pthread_create(&tid[i],NULL,Routine,(void*)buffer); //Pass thread 1 parameter } while(1) { printf("main thread:pid:%d,ppid:%d\n",getpid(),getppid()); sleep(2); } return 0; }
7. Display your thread ID:pthread_self()
#include<stdio.h> #include<pthread.h> #include<unistd.h> #include<sys/types.h> void *Routine(void *arg) { char *msg = (char*)arg; while(1) { printf("%s: pid:%d,ppid:%d,tid:%lu\n",msg,getpid(),getppid(),pthread_self()); sleep(1); } } int main() { pthread_t tid[5]; //Create thread for(int i = 0; i < 5; i++) { char buffer[64]; sprintf(buffer,"thread %d",i); pthread_create(&tid[i],NULL,Routine,(void*)buffer); //Pass thread 1 parameter printf("%s tid is:%lu\n",buffer,tid[i]); } while(1) { printf("main thread:pid:%d,ppid:%d,tid:%lu\n",getpid(),getppid(),pthread_self()); sleep(2); } return 0; }
Note: call the ID of your own thread: pthread_ Self() is similar to getpid(), but the type is% lu. In this case, the thread ID of the user level native thread library is obtained, and the relationship with LWP is 1:1
2, Thread waiting
1. Thread waiting: phread_join(), by default, waits in the form of blocking. If you don't wait, it may become a zombie process and cause memory leakage
#include<stdio.h> #include<pthread.h> #include<unistd.h> #include<sys/types.h> void *Routine(void *arg) { char *msg = (char*)arg; int count = 0; while(count < 5) { printf("%s: pid:%d,ppid:%d,tid:%lu\n",msg,getpid(),getppid(),pthread_self()); sleep(1); count++; } return NULL; } int main() { pthread_t tid[5]; //Create thread for(int i = 0; i < 5; i++) { char buffer[64]; sprintf(buffer,"thread %d",i); pthread_create(&tid[i],NULL,Routine,(void*)buffer); //Pass thread 1 parameter printf("%s tid is:%lu\n",buffer,tid[i]); } printf("main thread:pid:%d,ppid:%d,tid:%lu\n",getpid(),getppid(),pthread_self()); //Thread waiting for(int i = 0; i < 5; i++) { pthread_join(tid[i],NULL); printf("thread %d[%lu] ... quit!\n",i,tid[i]); } return 0; }
2. Get exit code
int pthread_join(pthread_t thread, void **retval)
retval: get the exit code of the waiting thread, which is usually used to verify whether the code is running and the result is correct.
#include<stdio.h> #include<stdlib.h> #include<pthread.h> #include<unistd.h> #include<sys/types.h> void *Routine(void *arg) { char *msg = (char*)arg; int count = 0; while(count < 5) { printf("%s: pid:%d,ppid:%d,tid:%lu\n",msg,getpid(),getppid(),pthread_self()); sleep(1); count++; } return (void*)10; } int main() { pthread_t tid[5]; //Create thread for(int i = 0; i < 5; i++) { char *buffer=(char*)malloc(64); sprintf(buffer,"thread %d",i); pthread_create(&tid[i],NULL,Routine,(void*)buffer); //Pass thread 1 parameter printf("%s tid is:%lu\n",buffer,tid[i]); } printf("main thread:pid:%d,ppid:%d,tid:%lu\n",getpid(),getppid(),pthread_self()); //Thread waiting for(int i = 0; i < 5; i++) { void *ret = NULL; pthread_join(tid[i],&ret); //Get exit code printf("thread %d[%lu] ... quit! code:%d\n",i,tid[i],ret); } return 0; }
In addition: multithreading needs to consider exceptions, but it can't
3, Thread termination
1. Why wait?
(1) The space of the thread that has exited is not released and is still in the address space of the process
(2) Creating a new thread does not reuse the address space of the thread that just exited
2. Normal termination
(1). return: XXX represents the end of the whole process
(2). exit(): the whole process is terminated
(3). Terminate a thread: pthread_exit()
(4). pthread_cancel(): cancels a thread. The cancellation is successful. The exit code is - 1
(5). Pthread in main_ Cancel (TID [0]) cancel other threads (recommended), and cancel threads with subscript 0
In addition:
1. Can a new thread cancel the main thread? Yes, but not recommended
2. In general, the thread must be waiting, just as the child process must be waiting
3. The thread can not be join ed or not, but it needs to be separated
4, Thread separation
pthread_detach()
#include<stdio.h> #include<stdlib.h> #include<pthread.h> #include<unistd.h> #include<sys/types.h> void *Routine(void *arg) { pthread_detach(pthread_self()); char *msg = (char*)arg; int count = 0; while(count < 5) { printf("%s: pid:%d,ppid:%d,tid:%lu\n",msg,getpid(),getppid(),pthread_self()); sleep(1); count++; } pthread_exit((void*)19); //Thread exit code // return (void*)10; } int main() { pthread_t tid[5]; //Create thread for(int i = 0; i < 5; i++) { char *buffer=(char*)malloc(64); sprintf(buffer,"thread %d",i); pthread_create(&tid[i],NULL,Routine,(void*)buffer); //Pass thread 1 parameter printf("%s tid is:%lu\n",buffer,tid[i]); } while(1){ printf("main thread:pid:%d,ppid:%d,tid:%lu\n",getpid(),getppid(),pthread_self()); sleep(1); } /* //Thread waiting for(int i = 0; i < 5; i++) { void *ret = NULL; pthread_join(tid[i],&ret); //Get exit code printf("thread %d[%lu] ... quit! code:%d\n",i,tid[i],ret); } */ return 0; }
How does the user layer know the corresponding thread?
There are many threads that need to be managed. Linux does not provide real threads, but only LWP, which means that the OS only needs to manage the execution flow of LWP kernel, and other data such as interfaces for users are managed by the thread library pthread library
pthread_t-type thread ID is essentially an address in a process address space.