#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void* f1(void * arg);
int main(int argc, char* argv[]){
if(argc != 3){
printf("Invalid number of arguments. Must pass two file names.\n");
exit(1);
}
pthread_t tid1, tid2;
void *rv1, *rv2;
pthread_create(&tid1, NULL, f1, (void*)argv[1]);
pthread_create(&tid2, NULL, f1, (void*)argv[2]);
pthread_join(tid1, &rv1);
pthread_join(tid2, &rv2);
int count1 = *((int*)rv1);
int count2 = *((int*)rv2);
printf("Characters in %s: %d\n", argv[1], count1);
printf("Characters in %s: %d\n", argv[2], count2);
return 0;
}
void* f1(void* args){
char* filename = (char*)args;
int *result = (int*)malloc(sizeof(int));
*result = 0;
char ch;
int fd = open(filename, O_RDONLY);
while((read(fd, &ch, 1)) != 0){
(*result)++;
}
close(fd);
pthread_exit((void*)result);
}
create 2 thread and join them to main thread. remmber we need to compile this with "-lpthread -D_REENTRANT"
Defining _REENTRANT causes the compiler to use thread safe (i.e. re-entrant) versions of several functions in the C library.
what data is shared
global data and static local data. The case of static local data is only significant if 2 or more threads execute the function containing static local variable at the same time.
dynamically allocated data in heap that has had its address put into a global/static variable
Data members of a class object that has 2 or more of its member functions caleld by different htreads at the same time.
what is not shared
Local variables are not shared. Even if 2 threads call the same function they will have different copies of the local variable in that function. This is because the local variables are kept on stack and every thread has its own stack.
Function parameters are not shared. In Languages like C, the parameters of function are also put on the stack & thus every thread will have its own copy of those as well
thread safe function
can be called simultaneously from multiple threads, even when the invocations use shared data. This is because each thread accesses shared data using some concurrency control mechanism
reentrant function
can also can be called simultaneously from multiple threads , but only if each invocation uses its own data
therefore thread-safe function is always reentrant, but a reentrant function is not always thread safe
Mutex
Mutual Exclusion device and is useful for protecting shared data strcutures from concurrent modifications, and implementing critical sections
A mutex has 2 possible states: unlocked (not owned by any thread) , and locked (owned by one thread). It can never be owned by 2 different threads simultaneously
A thread attempting to lock a mutex that is laready locked by another thread is suspended until the owner thread unlocks the mutex
Linux guarantees that race condition do not occur among threads attempting to lock a mutex
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void * f1(void * arg);
pthread_mutex_t mut;
int main(){
pthread_mutexattr_t mutattr;
pthread_mutexattr_init(&mutattr);
pthread_mutexattr_settype(&mutattr, PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init(&mut, &mutattr);
pthread_t t1;
pthread_create(&t1, NULL, f1,NULL);
pthread_join(t1,NULL);
printf("Bye Bye from main\n");
return 0;
}
void * f1(void * arg){
pthread_mutex_lock(&mut);
pthread_mutex_lock(&mut);
printf("Locking an already locked error checking mutex returns with error\n");
pthread_mutex_unlock(&mut);
pthread_exit(NULL);
}
to check thread error checking we need to use "pthread_mutexattr_t" and set attribute to our mutex ("mut")
when we execute blocking terminal will not happen and return with error.
_NP = non portable
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex;
pthread_cond_t is_zero;
long long shared_data = 100000000;
void* thread_function(void*);
int main (){
pthread_t tid;
pthread_cond_init(&is_zero, NULL);
pthread_mutex_init(&mutex, NULL);
pthread_create (&tid, NULL, thread_function, NULL);
//main thread waits till the shared data reaches zero
pthread_mutex_lock(&mutex);
if (shared_data != 0)
pthread_cond_wait(&is_zero, &mutex);
pthread_mutex_unlock(&mutex);
printf("shared_data = %lld \n", shared_data);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&is_zero);
return 0;
}
void* thread_function(void* arg){
while(shared_data > 0){
pthread_mutex_lock(&mutex);
shared_data--;
pthread_mutex_unlock(&mutex);
}
pthread_cond_signal(&is_zero);
return NULL;
}
main thraed checks if share_data is zero since it is not it goes to wait queue until the other thread signal() it with "pthread_cond_signal(&is_zero)" in this case "is_zero" is the queue.
'Operating System > System Programming(Arif Butt)' 카테고리의 다른 글
Lec34) Socket Programming Part-1 (0) | 2021.10.25 |
---|---|
Lec33) Overview of TCP/IP Architecture and Service (0) | 2021.10.23 |
Lec29, 30) Programming With Shared Memory , Memory Mapped Files (0) | 2021.07.24 |
Lec28) Message Queues (0) | 2021.07.21 |
Lec26,27) Programming UNIX Pipes and Named Pipes (0) | 2021.07.20 |