Linux下有多种方式来处理线程同步,常见的有如下几种机制:
(1)信号量
(2)互斥锁
(3)条件变量
(4)读写锁
1、信号量
类比进程一样,线程也是可以通过信号量来实现通信的,但相对于进程而言是轻量级的。
#include <semaphore.h>
初始化:int sem_init(sem_t* sem, int pshared, unsigned int value);
参数:
sem - 指定要初始化的信号量;
pshared - 信号量 sem 的共享选项,linux只支持0,表示它是当前进程的局部信号量;
value - 信号量 sem 的初始值。
信号量加1:
int sem_post(sem_t *sem);
信号量减1:
int sem_wait(sem_t *sem);
信号量销毁:
int sem_destroy(sem_t *sem);
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>
#define return_if_fail(p) if((p) == 0){printf ("[%s]:func error!\n", __func__);return;}
typedef struct _PrivInfo
{
sem_t s1;
sem_t s2;
time_t end_time;
}PrivInfo;
static void info_init (PrivInfo* prifo);
static void info_destroy (PrivInfo* prifo);
static void* pthread_func_1 (PrivInfo* prifo);
static void* pthread_func_2 (PrivInfo* prifo);
int main (int argc, char** argv)
{
pthread_t pt_1 = 0;
pthread_t pt_2 = 0;
int ret = 0;
PrivInfo* prifo = NULL;
prifo = (PrivInfo* )malloc (sizeof (PrivInfo));
if (prifo == NULL)
{
printf ("[%s]: Failed to malloc priv.\n");
return -1;
}
info_init (prifo);
ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, prifo);
if (ret != 0)
{
perror ("pthread_1_create:");
}
ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, prifo);
if (ret != 0)
{
perror ("pthread_2_create:");
}
pthread_join (pt_1, NULL);
pthread_join (pt_2, NULL);
info_destroy (prifo);
return 0;
}
static void info_init (PrivInfo* prifo)
{
return_if_fail (prifo != NULL);
prifo->end_time = time(NULL) + 10;
sem_init (&prifo->s1, 0, 1);
sem_init (&prifo->s2, 0, 0);
return;
}
static void info_destroy (PrivInfo* prifo)
{
return_if_fail (prifo != NULL);
sem_destroy (&prifo->s1);
sem_destroy (&prifo->s2);
free (prifo);
prifo = NULL;
return;
}
static void* pthread_func_1 (PrivInfo* prifo)
{
return_if_fail (prifo != NULL);
while (time(NULL) < prifo->end_time)
{
sem_wait (&prifo->s2);
printf ("pthread1: pthread1 get the lock.\n");
sem_post (&prifo->s1);
printf ("pthread1: pthread1 unlock\n");
sleep (1);
}
return;
}
static void* pthread_func_2 (PrivInfo* prifo)
{
return_if_fail (prifo != NULL);
while (time (NULL) < prifo->end_time)
{
sem_wait (&prifo->s1);
printf ("pthread2: pthread2 get the unlock.\n");
sem_post (&prifo->s2);
printf ("pthread2: pthread2 unlock.\n");
sleep (1);
}
return;
}
2、互斥锁
锁的种类有很多,互斥锁、文件锁、读写锁…其实信号量说白了也是一种锁。使用锁的目的是达到同步的作用,使共享资源在同一时间内,只有能在一个进程或者线程对它进行操作。
(举例:此时有两个线程,分别是线程A,B。A和B现在共享资源M,为了同步A,B,使得同一时刻只有一个线程对M进行操作,于是,很自然的会对A中对M资源先lock,等到A对M操作完毕之后,然后再进行操作unlock,这时候B在进行lock,操作完进行unlock操作。 )
初始化:
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutex_attr_t *mutexattr);
阻塞加锁
int pthread_mutex_lock(pthread_mutex *mutex);
非阻塞加锁
int pthread_mutex_trylock( pthread_mutex_t *mutex);
解锁(要求锁是lock状态,并且由加锁线程解锁)
int pthread_mutex_unlock(pthread_mutex *mutex);
销毁锁(此时锁必需unlock状态,否则返回EBUSY)
int pthread_mutex_destroy(pthread_mutex *mutex);
3.条件变量
条件变量是利用线程间共享全局变量进行同步的一种机制。
条件变量的基本操作有触发条件、等待条件、挂起线程知道其他线程出发条件。
初始化条件变量
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);
无条件等待
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
计时等待
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
激发条件
(1)激活一个等待该条件的线程(存在多个等待线程时按入队顺序激活其中一个)
int pthread_cond_signal(pthread_cond_t *cond);
(2)激活所有等待线程
int pthread_cond_broadcast(pthread_cond_t *cond);
销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond);
#include <stdio.h>
#include <pthread.h>
#include "stdlib.h"
#include "unistd.h"
pthread_mutex_t mutex;
pthread_cond_t cond;
void hander(void *arg)
{
free(arg);
(void)pthread_mutex_unlock(&mutex);
}
void *thread1(void *arg)
{
pthread_cleanup_push(hander, &mutex);
while(1)
{
printf("thread1 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
printf("thread1 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(4);
}
pthread_cleanup_pop(0);
}
void *thread2(void *arg)
{
while(1)
{
printf("thread2 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
printf("thread2 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
pthread_t thid1,thid2;
printf("condition variable study!\n");
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
pthread_create(&thid1,NULL,thread1,NULL);
pthread_create(&thid2,NULL,thread2,NULL);
sleep(1);
do{
pthread_cond_signal(&cond);
}while(1);
sleep(20);
pthread_exit(0);
return 0;
}