Introduction to POSIX thread 1 2016/5/25

Download Report

Transcript Introduction to POSIX thread 1 2016/5/25

Introduction to
POSIX thread
1
2016/5/25
2
outline
Basic thread functions and thread
management
 Mutual exclusion
 Condition variables
 Example program

2016/5/25
3
A simple example
void *thread_routine(){
// …
pthread_exit(0); // or return NULL to terminate this thread
}
int main(){
pthread_t tid; // the thread identifier
pthread_attr_t attr; // set of thread attributes
// …
pthread_attr_init(&attr); // get the default attributes
// create the thread
pthread_create(&tid, &attr, (void*) thread_routine, NULL);
// …
pthread_join(tid, NULL); // wait for the thread to exit
// …
}
2016/5/25
4
A simple example cont’d
Main Thread
Thread routine
pthread_create();
Time
pthread_join();
pthread_exit();
2016/5/25
Thread identifiers and
attribute

pthread_t


5
Thread id, 用來識別thread
pthread_attr_t

Thread屬性, 包含優先權、初始的
stack大小、是否為daemon thread…
等, 一般來說都使用系統預設值
2016/5/25
6
Thread creation

建立thread
#include <pthread.h>
int pthread_create(pthread_t *tid,
const pthread_attr_t *attr,
void*(*some_routine) (void*),
void *arg);



回傳值: 如果成功, 傳回0; 如果錯誤, 傳回正的integer
attr用來設定thread attribute, 設成NULL表示使用系統
預設值
指定some_routine給此thread執行, arg為some_routine
所需的參數, 型態皆為generic pointer
2016/5/25
7
Thread attributes

設定thread屬性
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);



使用系統預設的thread attribute
回傳值: 如果成功, 傳回0; 如果錯誤, 傳回正的
integer
設定thread attribute的詳細方法, 請查閱man
page of pthread_attr_init
2016/5/25
Thread termination and
join
8
#include <pthread.h>
void pthread_exit(void* status);



通常在thread routine裡面呼叫此函式
等同於 return NULL
status不可以是thread routine內的local variables
#include <pthread.h>
int pthread_join(pthread_t tid, void **status);

等待id為tid的thread結束
通常在main thread裡面呼叫此function, main thread會
停在此處直到thread結束

必須明確指定tid, status為thread routine的回傳值

2016/5/25
Other thread management
function
9
#include <pthread.h>
pthread_t pthread_self(void);

取得自己的thread identifier
#include <pthread.h>
int pthread_detach(pthread_t tid);

Thread分成兩種型式: joinable和detached


當joinable thread 結束時, 它的thread identifier和
status都會一直保留直到其它thread對它呼叫
pthread_join()為止
當detached thread結束時, 所有資源都會被release, 因
此無法等它結束
2016/5/25
10
Mutex: Mutual Exclusion




A mutex is used by multiple threads to ensure
the integrity of a shared object that they
access by allowing only one thread to access it
at a time.
A mutex has two states, locked and unlocked.
Each thread locks a mutex before it accesses
the shared object and unlocks the mutex when it
is finished accessing that object.
If the mutex is locked by another thread, the
thread requesting the lock waits for the mutex
to be unlocked.
2016/5/25
Mutex: Mutual Exclusion
(cond.)
11
For each shared object, all threads
accessing that data must use the
same mutex.
 Each mutex must be initialized
before use.
 Define mutexes as global variables
since they are generally required to
be visible to all the threads that
contend.

2016/5/25
A Race Condition
Thread 1
12
Thread 2
Write A
Time
Write A
Read A
Write B
Write B
Read B
2016/5/25
13
Synchronization
Lock Mutex
Thread 1
Thread 2
Write A
Read A
Time
Wait to lock Mutex
Write B
Unlock Mutex
Lock Mutex
Write A
Write B
Read B
2016/5/25
Unlock Mutex
14
Initialize a Mutex
Initialize the mutex by calling
pthread_mutex_init. You can also
use the static initializer
PTHREAD_MUTEX_INITIALIZER.
 Initialize a mutex only once.

#include <pthread.h>
pthread_mutex_t counter_mutex =
PTHREAD_MUTEX_INITIALIZER;
2016/5/25
15
Lock/Unlock a Mutex
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t * mptr);
int pthread_mutex_unlock(pthread_mutex_t * mptr);
Both return: 0 if OK, positive value on error
2016/5/25
Example program
16
#include <pthread.h>
#define NLOOP 5000
int counter; /* incremented by threads */
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
void *doit(void *);
int main(int argc, char **argv) {
pthread_t tidA, tidB;
pthread_create(&tidA, NULL, &doit, NULL);
pthread_create(&tidB, NULL, &doit, NULL);
}
/* wait for both threads to terminate */
pthread_join(tidA, NULL);
pthread_join(tidB, NULL);
exit(0);
2016/5/25
Example program (cond.)
17
void * doit(void *vptr) {
int i, val;
/* Each thread fetches, prints, and increments the counter NLOOP
times. The value of the counter should increase monotonically. */
}
for (i = 0; i < NLOOP; i++) {
pthread_mutex_lock(&counter_mutex);
val = counter;
printf("%d: %d\n", pthread_self(), val + 1);
counter = val + 1;
pthread_mutex_unlock(&counter_mutex);
}
return (NULL);
2016/5/25
The value is incremented monotonically and the final value printed is always
10,000.
18
Condition Variables
A condition variable allows a thread
to block its own execution until a
condition is met (some shared data
reaches a particular state).
 A condition variable is a
synchronization object used in
conjunction with a mutex.

2016/5/25
19
Condition Variables (cond.)
A mutex controls access to shared
data; a condition variable allows
threads to wait for that data to
enter a defined state.
 The state is defined by a Boolean
expression called a predicate.

2016/5/25
20
Initialize A Condition Variable

Use pthread_cond_init routine to
initialize a condition variable. You
can also use the static initializer
PTHREAD_COND_INITIALIZER.
#include <pthread.h>
pthread_cond_t ndone_mutex =
PTHREAD_COND_INITIALIZER;
2016/5/25
21
Conditional Wait/Signal
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *cptr,
pthread_mutex_t *mptr);
int pthread_cond_signal(pthread_cond_t *cptr);
Both return: 0 if OK, positive value on error
2016/5/25
Example program
22
// server.c
// server will have at least 10 threads at the same time
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t done_cond = PTHREAD_COND_INITIALIZER;
#define serverPort 5566
#define POOL 10 // max # of threads that are serving.
int counter = 0; // to count the # of connections which are served now
void* handler(void* input);
int main(int argc,char* argv[]) {
int servSockFD;//listening socket fd
pthread_t childPid;//thread pid
socklen_t clientLen;//client address length
int *new_con;// a socket for a new client
struct sockaddr_in clientAddr,serverAddr;// client/server address
2016/5/25
Example program (cond.)
23
// open a listening socket
if ((servSockFD = socket(AF_INET,SOCK_STREAM,0)) < 0)
cout<<"Error with open a socket"<<endl;
// set server ip address
bzero(&serverAddr,sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(atoi(serverPort));
// bind address
bind(servSockFD,(struct
sockaddr*)&serverAddr,sizeof(serverAddr));
listen(servSockFD,5);
2016/5/25
Example program (cond.)
24
for( ; ; ){ //listening
clientLen = sizeof(clientAddr);
new_con = (int*) malloc(sizeof(int));
}
}
if ((*new_con = accept(servSockFD,(struct sockaddr*)&clientAddr,
&clientLen)) < 0) exit(-1);
else
{
pthread_mutex_lock(& counter_mutex);
while(counter >= POOL) // Wait for thread to terminate
pthread_cond_wait(&done_cond, & counter_mutex);
counter ++; // increase the counter
pthread_mutex_unlock(& counter_mutex);
pthread_create( &childPid, NULL, handler, new_con);
}
return 0;
2016/5/25
Example program (cond.)
25
void* handler(void* arg)
{
pthread_detach(pthread_self());
int connfd; // socket fd for connection
connfd = *((int *) arg);
free(arg);
}
/* do something
work done */
//A thread notifies the main loop that it is terminating by
//decrementing the counter while its mutex lock is held and by
// signaling the condition variable.
close(connfd);
pthread_mutex_lock( & counter_mutex );
counter --;
pthread_cond_signal( &done_cond);
pthread_mutex_unlock( & counter_mutex);
2016/5/25
26
References

POSIX thread programming
http://www.llnl.gov/computing/tutorials/pthreads/

Chapter 23, UNIX Network Programming,
Volume 1, 3rd ed., W. Richard Stevens.
2016/5/25