Introduction of Synchronization
Several variables changing over time keep relationship with each other.
Asynchronous != synchronizate
- Thread Synchronization
Let’s image two threads, the fisrt thread push data into the buf and the second thread pull data from the buf. In this case, they have to touch some conditon that the second thread can only do after the first thread.
In a short the Thread Synchronization is that some threads know each in an exact time point.
Producer-Consumer problem
In fact, the Producer is just like the first thread in the previous example and the consumer is the second thread.
So where is the problem.
The consumer may read the buf when there was no data in the buf. The data which read was useless and can damage the program.
As the producer, if it continues to add data to the buf ignore the empty place in the buf, buf is to overflow.
Condition Variables(CV)
- Definition
A condition variable is an explicit queue that threads can put themselves on when some state of execution is not as desired.
pthread_cond_t cv;
To declare a condition variable
API
wait(cv, mutex);
Assume the caller having mutex
Set out the mutex and go to sleep
signal/notify(cv);
wake up someone
broadcast/notifyAll(cv);
wake up everyone
p-c by cv
void Tproduce() {
(&lk);
mutex_lockif (conunt == n) cond_wait(&cv, &lk);
("("); count++; cond_signal(&cv);
printf(&lk);
mutex_unlock}
void Tconsume() {
(&lk);
mutex_lockif (count == 0) cond_wait(&cv, &lk);
(")"); count--l cond_signal(&cv);
printf(&lk);
mutex_unlock}
paralled compute by cv
struct job {
void (*run)(void *arg)
void *arg;
}
while (1) {
struct job *job;
(&mutex);
mutex_lockwhile (! (job = get_job())) {
(&cv, &mutex);
wait}
(&mutex);
mutex_unlock->run(job->arg);
job}
Semaphores
By cv we can coordinate threads in defend of spinning. But can we coordinate more threads not one to use the shared resource.
Semaphores invited by Edsger Dijkstra help us work better.
In cv only one can operate when get the critical conditon. Why not create more chances? Thread who can create a semaphore and enter the operation when it satisfies the condition.
#include <semaphore.h>
;
sem_t s(&s, 0, 1); sem_init
Two Operation
- P(proberen)
try+decrease; wait; down; in
- V(verhogen)
increase; post;up;out
p-c by semaphore
void producer() {
(&empty);
P("(");
printf(&fill);
V}
void consumer() {
(&fill);
P(")");
printf(&empty);
V}