what is a thread? multiple strands of execution in a single program are called threads. a more precise definition is that a thread is a sequence of control within a process. compared with process , the new thread of execution gets its own stack(so are the local variables)but shares global variables,global variables,file descriptors,singal handlers,and its current directory state with the process that created it.
let's come up with some functions about making use of thread:
these three are very inportant in creating thread and manipulating thread.let's come to the first one
as you can see above,it seems so complex that you don't know how to analyse it, it's ok,i will split it up and show you one by one.begin with the parameter.
pthread_t * thread : an identifier to the thread you create ,later you will use it to manipulate the thread
pthread_attr_t * attr : this parameter emplifies the attributes of the thread ,normally,we don't use it so here you can use NULL in replace of it
void *(*start_routine)(void *) : you must pass the address of a function taking a pointer to void as a parameter and the function will return a pointer t void ,thus you can pass any type of single argument and return a pointer to any type
void * arg : it is the parameter the start_routin function may use , it is the same with the function above , it can be any type
after creating thread , the pthread_exit() function terminates the calling thread,return a pointer to an object, and the retval(can be any type) shouldn't be a local variable,for that the local area will become unavailable after exitting,and the exitocde (type:string ,int ,char[] ,char...) will written to the location pointed by retval.
the last one with two parameter is function like wait of waitpid in process,the first parameter is the thread for which to wait,the second argument is a pointer to a pointer that itself points to the returnvalue from the thread.
we don't show you an example about making thread now ,late i will show you another example which include multithread and semaphores together. so we start semaphores now, what is semaphore ? a semaphore is a special type of variable that can be incremented and decremented .but cucial access to the variables is guaranteed to be atomic,even in a multithreaded program,it make it sure that all threads are executed in a sequence.
there are two types of atomic manipulation about synchronization one is semaphore another is mutex,i will give them all to you first and then explain it to you later i will show you an example about synchronization.
#include <semaphore.h>
/*initialize the semaphore pointed by sem , if pshared==0 , then the sem can only be used within the process ,between the thread .otherwise , it can be shared between processes , value means the object sem has when it was created */
int sem_init(sem_t * sem,int pshared,unsigned int value);
/*waiting for an semaphore , and if sem is nozero sem will reduce one atomically otherwise if it equals 0 then the thread(process will block until it wasn't */
int sem_wait(sem_t * sem);
/*when a process(thread) used the semaphore , it release it*/
int sem_post(sem_t * sem);
/*destroy the sem , if you destroy an sem which another thread(process) is waitting for ,you will get an error*/
int sem_destroy(sem_t * sem);
#include <pthread.h>
/*initialize an mutex whose value can only be 0 or 1 , normally we don't need the mutex to have any attributes , so give it NULL*/
int pthread_mutex_init(pthread_mutex_t * mutex,const pthread_mutexattr_t *mutexattr);
/*apply for the mutex*/
int pthread_mutex_lock(pthread_mutex_t * mutex);
/*release the mutex*/
int pthread_mutex_unlock(pthread_mutex_t * mutex);
/*destroy the mutex*/
int pthread_mutex_destroy(pthread_mutex_t * mutex);
the way to cancel a thread is very easy , so there is no need for me to explain it carefully,find it on the manual page
let's come up with some functions about making use of thread:
#include <pthread.h>
int pthread_create(pthread_t * thread,pthread_attr_t * attr,void *(*start_routine)(void *),void * arg);
void pthread_exit(void * retval);
int pthread_join(pthread_t th, void **thread_return);
these three are very inportant in creating thread and manipulating thread.let's come to the first one
as you can see above,it seems so complex that you don't know how to analyse it, it's ok,i will split it up and show you one by one.begin with the parameter.
pthread_t * thread : an identifier to the thread you create ,later you will use it to manipulate the thread
pthread_attr_t * attr : this parameter emplifies the attributes of the thread ,normally,we don't use it so here you can use NULL in replace of it
void *(*start_routine)(void *) : you must pass the address of a function taking a pointer to void as a parameter and the function will return a pointer t void ,thus you can pass any type of single argument and return a pointer to any type
void * arg : it is the parameter the start_routin function may use , it is the same with the function above , it can be any type
after creating thread , the pthread_exit() function terminates the calling thread,return a pointer to an object, and the retval(can be any type) shouldn't be a local variable,for that the local area will become unavailable after exitting,and the exitocde (type:string ,int ,char[] ,char...) will written to the location pointed by retval.
the last one with two parameter is function like wait of waitpid in process,the first parameter is the thread for which to wait,the second argument is a pointer to a pointer that itself points to the returnvalue from the thread.
we don't show you an example about making thread now ,late i will show you another example which include multithread and semaphores together. so we start semaphores now, what is semaphore ? a semaphore is a special type of variable that can be incremented and decremented .but cucial access to the variables is guaranteed to be atomic,even in a multithreaded program,it make it sure that all threads are executed in a sequence.
there are two types of atomic manipulation about synchronization one is semaphore another is mutex,i will give them all to you first and then explain it to you later i will show you an example about synchronization.
#include <semaphore.h>
/*initialize the semaphore pointed by sem , if pshared==0 , then the sem can only be used within the process ,between the thread .otherwise , it can be shared between processes , value means the object sem has when it was created */
int sem_init(sem_t * sem,int pshared,unsigned int value);
/*waiting for an semaphore , and if sem is nozero sem will reduce one atomically otherwise if it equals 0 then the thread(process will block until it wasn't */
int sem_wait(sem_t * sem);
/*when a process(thread) used the semaphore , it release it*/
int sem_post(sem_t * sem);
/*destroy the sem , if you destroy an sem which another thread(process) is waitting for ,you will get an error*/
int sem_destroy(sem_t * sem);
#include <pthread.h>
/*initialize an mutex whose value can only be 0 or 1 , normally we don't need the mutex to have any attributes , so give it NULL*/
int pthread_mutex_init(pthread_mutex_t * mutex,const pthread_mutexattr_t *mutexattr);
/*apply for the mutex*/
int pthread_mutex_lock(pthread_mutex_t * mutex);
/*release the mutex*/
int pthread_mutex_unlock(pthread_mutex_t * mutex);
/*destroy the mutex*/
int pthread_mutex_destroy(pthread_mutex_t * mutex);
the way to cancel a thread is very easy , so there is no need for me to explain it carefully,find it on the manual page
#include <pthread.h>
int pthread_cancel(pthread_t pthread);
int pthread_setcancelstate(int state,int * oldstate);
int pthread_setcanceltype(int type,int * oldtype);
now show you anexample about making thread:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
/*producer and consumer problem*/
void produce();
void consume();
void * start_routine(void * arg);
sem_t empty;
sem_t full;
pthread_mutex_t mutex;
int consume_count=0;
int produce_count=0;
int main(){
pthread_t new_thread;
void * return_val;
/*initialize the semaphores*/
if(sem_init(&empty,0,0) != 0){
perror("sem_init error\n");
exit(0);
}
if(sem_init(&full,0,10) != 0){
perror("sem_init error\n");
exit(0);
}
if(pthread_mutex_init(&mutex,NULL) != 0){
perror("mutex_init error\n");
exit(0);
}
if(pthread_create(&new_thread,NULL,start_routine,NULL) != 0){
perror("creating thread eror\n");
exit(0);
}
while(1){
produce();
if(produce_count==10){
break;
}
}
if(pthread_cancel(new_thread) != 0){
perror("pthread_cancel error\n");
exit(0);
}
// pthread_join(new_thread,&return_val);
sem_destroy(&empty);
sem_destroy(&full);
pthread_mutex_destroy(&mutex);
printf("%s\n",(char *)return_val);
return 0;
}
/*consume*/
void * start_routine(void * arg){
if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL) != 0){
perror("set cancel state error\n");
exit(0);
}
if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL) != 0){
perror("set cancel type error\n");
exit(0);
}
while(1){
consume();
}
pthread_exit("consume ok");
}
/*producer action*/
void produce(){
sem_wait(&empty);
pthread_mutex_lock(&mutex);
printf("producing %d ...\n",produce_count);
sleep(1);
printf("produce %d ok\n",produce_count++);
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
/* consumer action*/
void consume(){
sem_wait(&full);
pthread_mutex_lock(&mutex);
printf("consuming %d ...\n",consume_count);
sleep(1);
printf("consume %d ok\n",consume_count++);
pthread_mutex_unlock(&mutex);
sem_post(&empty);
}