互斥锁(互斥量)
创建互斥锁
pthread_mutex_t mutex;
初始化互斥锁
pthread_mutex_init(pthread_mutex_t* mutex,
const pthread_mutexattr_t* attr
);
销毁互斥锁
pthread_mutex_unlock(pthread_mutex_t *mutex);
加锁
//如果加锁的时候发现锁已经被锁上了,线程会一直阻塞在这个位置
pthread_mutex_lock(pthread_mutex_t *mutex);
//尝试加锁,失败返回,不阻塞
pthread_mutex_trylock(pthread_mutex_t *mutex);
解锁
pthread_mutex_unlock(pthread_mutex_t *mutex);
实例
#include <stdio.h> #include <signal.h> #include <unistd.h> #include <string.h> #include <pthread.h> #define MAX 10000 int number; //创建一把互斥锁 pthread_mutex_t mutex; void* funcA_num(void* arg) { int i; for(i=0; i<MAX; i++) { //加锁 pthread_mutex_lock(&mutex); int cur = number; cur++; number = cur; printf("Thread A, id = %lu, number = %d ", pthread_self(), number); //解锁 pthread_mutex_unlock(&mutex); usleep(10); } return NULL; } void* funcB_num(void* arg) { int i; for(i=0; i<MAX; i++) { //加锁 pthread_mutex_lock(&mutex); int cur = number; cur++; number = cur; printf("Thread B, id = %lu, number = %d ", pthread_self(), number); //解锁 pthread_mutex_unlock(&mutex); usleep(10); } return NULL; } int main(int argc, const char* argv[]) { pthread_t p1, p2; //初始化互斥锁 pthread_mutex_init(&mutex, NULL); //创建两个子进程 pthread_create(&p1, NULL, funcA_num, NULL); pthread_create(&p2, NULL, funcB_num, NULL); //阻塞,回收资源 pthread_join(p1, NULL); pthread_join(p2, NULL); //释放互斥锁资源 pthread_mutex_destroy(&mutex); return 0; }
条件变量
创建条件变量
pthread_cond_t cond;
初始化一个条件变量
pthread_cond_init( pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr );
销毁一个条件变量
pthread_cond_destroy(pthread_cond_t *cond);
阻塞等待一个条件变量
pthread_cond_wait( pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex );
-
阻塞线程并将已经上锁的mutex解锁
- 在解除阻塞时会对互斥锁加锁
限时等待一个条件变量
pthread_cond_timedwait( pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime );
唤醒至少一个阻塞在条件变量上的线程
pthread_cond_signal(pthread_cond_t *cond);
唤醒全部阻塞在条件变量上的线程
pthread_cond_broadcast(pthread_cond_t *cond);
使用互斥锁加条件变量实现生成者消费者模型
#include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <stdlib.h> typedef struct node { int data; struct node* next; }Node; Node* head = NULL; pthread_mutex_t mutex; pthread_cond_t cond; void* producer(void* arg) { while(1) { Node* pnew = (Node*)malloc(sizeof(Node)); pnew->data = rand() % 1000; pthread_mutex_lock(&mutex); pnew->next = head; head = pnew; printf("produce: %lu, %d ", pthread_self(), pnew->data); pthread_mutex_unlock(&mutex); pthread_cond_signal(&cond); sleep(rand() % 3); } return NULL; } void* customer(void* arg) { while(1) { pthread_mutex_lock(&mutex); if(head == NULL) { pthread_cond_wait(&cond, &mutex); } Node* pdel = head; head = head->next; printf("customer: %lu, %d ", pthread_self(), pdel->data); free(pdel); pthread_mutex_unlock(&mutex); } return NULL; } int main(int argc, const char* argv[]) { pthread_t p1, p2; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); pthread_create(&p1, NULL, producer, NULL); pthread_create(&p2, NULL, customer, NULL); pthread_join(p1, NULL); pthread_join(p2, NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); return 0; }
信号量(高级互斥锁)
创建信号量
sem_t sem;
初始化信号量
sem_init(sem_t* sem, int pshared, unsigned int value);
pshared:
- 0:线程同步
- 1:进程同步
value:最多有几个线程操作共享资源
销毁信号量
sem_destroy(sem_t *sem);
加锁
sem_wait(sem_t *sem);
调用一次相当于sem值减一,如果sem值为0线程会阻塞
解锁
sem_post(sem_t *sem);
调用一次相当于sem值加一
尝试加锁
sem_trywait(sem_t *sem);
限时尝试加锁
sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
使用信号量实现生成者消费者模型
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <semaphore.h> sem_t produce_sem; sem_t custom_sem; typedef struct node { int data; struct node* next; }Node; Node *head = NULL; void* producer(void * arg) { while(1) { sem_wait(&produce_sem); Node *pnew = (Node*)malloc(sizeof(Node)); pnew->data = rand()%1000; pnew->next = head; head = pnew; printf("producer: %lu, %d ", pthread_self(), pnew->data); sem_post(&custom_sem); sleep(rand()%5); } return NULL; } void* customer(void* arg) { while(1) { sem_wait(&custom_sem); Node* pdel = head; if(head == NULL) { exit(1); } head = head->next; printf("customer: %lu, %d ", pthread_self(), pdel->data); free(pdel); sem_post(&produce_sem); sleep(rand()%5); } return NULL; } int main(int argc, const char* argv[]) { pthread_t thid[2]; sem_init(&produce_sem, 0, 4); sem_init(&custom_sem, 0, 0); pthread_create(&thid[0], NULL, producer, NULL); pthread_create(&thid[1], NULL, customer, NULL); int i; for(i=0; i<2; i++) { pthread_join(thid[i], NULL); } sem_destroy(&produce_sem); sem_destroy(&custom_sem); return 0; }