线程同步方法:

  1.  互斥锁
     

      lock_the_mutex(...);

  临界区

  unlock_the_mutex(...);

 

互斥锁通常用于保护由多个线程或多个进程共享的共享数据(Share Data)

 

互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源。比如对全局变量的访问,有时要加锁,操作完了,再解锁。

 

A线程的临界区中的逻辑一次性执行完再解锁,其它线程在A线程解锁前没有办法拿到锁,无法执行。目的是防止出现A线程中临界区中的逻辑执行到一半的时候,其它线程打断A线程执行,之后再执行剩余的部分(其它线程不能拿到锁,所以阻塞)。

 

#include <pthread.h> 

 

static  pthread_mutex_t  alock;  //定义锁

 

pthread_mutex_init(&alock, (const pthread_mutexattr_t *) NULL);    //初始化锁

 

pthread_mutex_lock(&alock);   //加锁, 若不能立刻获得锁, 将阻塞在这里。

……..

pthread_mutex_unlock(&alock);   //解锁

 

2.   条件变量

 

条件变量的使用必须有互斥锁配合。发送信号与等待信号。互斥锁用于上锁,条件变量则用于等待。一般来说,在一个进程/线程中调用pthread_cond_wait(..)等待某个条件的成立,此时该进程阻塞在这里,另外一个进程/线程进行某种操作,当某种条件成立时,调用pthread_cond_signal(...)来发送信号,从而使pthread_cond_wait(...)开始执行。此处要注意的是,这里所谈到的信号,不是系统级别的SIGXXXX信号,只是用信号这个词语更容易理解。条件变量与信号量更接近或者就可以认为是信号量。

  一个进程/线程要等到临界区的共享数据达到某种状态时再进行某种操作,而这个状态的成立,则是由另外一个进程/线程来完成后发送信号来通知的。

其实想一想,pthread_cond_wait函数也可以用一个while死循环来等待条件的成立,但要注意的是,使用while死循环会严重消耗CPU,而

pthread_cond_wait则是采用线程睡眠的方式,它是一种等待模式,而不是一直的检查模式。

  总的来说,给条件变量发送信号的代码大体如下:

  pthread_mutex_lock(&mutex);

  设置条件为真

  pthread_mutex_unlock(&mutex);  

      pthread_cond_signal(&cond);  //发送信号

  等待条件并进入睡眠以等待条件变为真的代码大体如下:

  pthread_mutex_lock(&mutex); 

  while(条件为假)

   pthread_cond_wait(&cond,&mutex);  //等待信号, wait必须放在lockunlock之间

  执行某种操作

  pthread_mutex_unlock(&mutex);

  在这里需要注意的是,pthread_cond_wait(&cond,&mutex)是一个原子操作,当它执行时,首先对mutex解锁,这样另外的线程才能得到锁来修改条件,pthread_cond_wait执行时会有一个先解锁的动作,执行完最后加锁。

 

使用举例:

 

#include <pthread.h>

 

static pthread_mutex_t alock;   //定义互斥锁

static pthread_cond_t  acond;  //定义信号量

 

 

pthread_mutex_init(&alock, (const pthread_mutexattr_t *) NULL);  //初始化锁

pthread_cond_init(&acond, (const pthread_condattr_t *) NULL);   //初始化条件变量

 

 

pthread_mutex_lock(&alock);

……

pthread_cond_signal(&acond);  //线程A中发送信号

…….

pthread_mutex_unlock(&alock);

 

 

 

struct timeval now;

struct timespec outtime;

int timeout_ms = 20;

int nsec;

gettimeofday(&now, NULL);

nsec = now.tv_usec * 1000 + (timeout_ms % 1000) * 1000000;

outtime.tv_sec = now.tv_sec + nsec/1000000000 + timeout_ms/1000;

outtime.tv_nsec = nsec % 1000000000;

pthread_mutex_lock(&alock);

//ret = pthread_cond_timedwait(&acond, &alock, &outtime); //线程B中等待信号,signal发送信号之前,一直阻塞在这里,如果过了20ms signal还没有发信号, 则开始执行,不再等待, 本质上加了一个超时检测。

ret = pthread_cond_wait(&acond, &alock);  //线程B中等待信号,signal发送信号之前,一直阻塞在这里。

if (ret != 0) {

ALOGE("%s: failed cond ! %d\n", __func__, ret);

}

pthread_mutex_unlock(&alock);

 

 

3.  信号量

 

作用: 保证线程或进程间的同步

 

信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作。

 

 

#include <semaphore.h>     //头文件

……

static  sem_t  sem_sync;   //定义变量

…….

sem_init(&sem_sync, 0, 0);   //初始化

……

sem_post(&sem_sync);   //线程A发送信号量

…….

sem_wait(&sem_sync);   //线程B等待信号量, post信号之前一直阻塞在这里

猜你喜欢

转载自blog.csdn.net/FPGASOPC/article/details/82907465