tinycthread

互斥锁声明

typedef struct {
  union {
    CRITICAL_SECTION cs;      /* Critical section handle (used for non-timed mutexes) */
    HANDLE mut;               /* Mutex handle (used for timed mutex) */
  } mHandle;                  /* Mutex handle */
  int mAlreadyLocked;         /* TRUE if the mutex is already locked */
  int mRecursive;             /* TRUE if the mutex is recursive */
  int mTimed;                 /* TRUE if the mutex is timed */
} mtx_t;

 互斥锁简介:

作用:保证共享数据操作的完整性,每个对象都有一个互斥锁的标记,

           用来保证任意时刻,只有一个线程访问改对象。

 

创建与销毁:创建声明互斥锁类型;销毁要求锁是开放状态才能释放资源,在linux中互斥锁不占用资源,只检查锁状态。

互斥锁属性(创建锁时指定):

类型 锁名 功能
PTHREAD_MUTEX_TIMED_NP 普通锁 当一个线程加锁后,其余线程形成一个等待队列,解锁后按照优先级访问获得锁
PTHREAD_MUTEX_RECURSIVE_NP 嵌套锁 允许同一线程对同一个锁成功获得多次,并通过unlock解锁;不同线程则解锁时重新竞争(存在计数器存储访问数量 访问为0时清空)
PTHREAD_MUTEX_ERRORCHECK_NP 检错锁

同一线程请求同一个锁返回EDEADLK,否则与普通锁相同

PTHREAD_MUTEX_ADAPTIVE_NP 适应锁 动作简单 等待解锁后重新竞争

锁操作:

1.加锁

2.解锁

3.测试加锁

int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
 
 

tinycthread

互斥锁类型:
类型 说明  
mtx_plain 普通锁  
mtx_recursive 递归锁(同一线程可调用多次)  
mtx_timed 普通锁并且支持超时  
使用:
 
1.mtx_plain:普通锁
2.mtx_timed:普通超时锁
3.mtx_plain & mtx_recursive:普通可递归锁
4.mtx_timed & mtx_recursive:普通可超时递归锁
 
函数说明:

1.初始化锁(返回成功/失败)

int mtx_init(mtx_t *mtx, int type) //输入以上三种type中一个
{
#if defined(_TTHREAD_WIN32_) //win下创建
  mtx->mAlreadyLocked = FALSE;
  mtx->mRecursive = type & mtx_recursive;
  mtx->mTimed = type & mtx_timed;
  if (!mtx->mTimed) //非可超时锁时声明
  {
    InitializeCriticalSection(&(mtx->mHandle.cs));
  }
  else
  {
    mtx->mHandle.mut = CreateMutex(NULL, FALSE, NULL); //创建一把锁
    if (mtx->mHandle.mut == NULL)
    {
      return thrd_error;
    }
  }
  return thrd_success;
#else //linux下创建
  int ret;
  pthread_mutexattr_t attr;//生成一个linux下的
  pthread_mutexattr_init(&attr);
  if (type & mtx_recursive)
  {
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  }
  ret = pthread_mutex_init(mtx, &attr);
  pthread_mutexattr_destroy(&attr);
  return ret == 0 ? thrd_success : thrd_error;
#endif
}

 

时间锁

int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)

参数:线程锁主体与时间空间(含秒与纳秒两个参数)

int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
{
#if defined(_TTHREAD_WIN32_)
  struct timespec current_ts;
  DWORD timeoutMs;

  if (!mtx->mTimed)
  {
    return thrd_error;
  }

  timespec_get(&current_ts, TIME_UTC);

  if ((current_ts.tv_sec > ts->tv_sec) || ((current_ts.tv_sec == ts->tv_sec) && (current_ts.tv_nsec >= ts->tv_nsec)))
  {
    timeoutMs = 0;
  }
  else
  {
    timeoutMs  = (DWORD)(ts->tv_sec  - current_ts.tv_sec)  * 1000;
    timeoutMs += (ts->tv_nsec - current_ts.tv_nsec) / 1000000;
    timeoutMs += 1;
  }

  /* TODO: the timeout for WaitForSingleObject doesn't include time
     while the computer is asleep. */
  switch (WaitForSingleObject(mtx->mHandle.mut, timeoutMs))
  {
    case WAIT_OBJECT_0:
      break;
    case WAIT_TIMEOUT:
      return thrd_timedout;
    case WAIT_ABANDONED:
    default:
      return thrd_error;
  }

  if (!mtx->mRecursive)
  {
    rd_assert(!mtx->mAlreadyLocked); /* Would deadlock */
    mtx->mAlreadyLocked = TRUE;
  }

  return thrd_success;
#elif defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS >= 200112L) && defined(_POSIX_THREADS) && (_POSIX_THREADS >= 200112L)//linux下自带timedlock可调用情况
  switch (pthread_mutex_timedlock(mtx, ts)) {
    case 0:
      return thrd_success;
    case ETIMEDOUT:
      return thrd_timedout;
    default:
      return thrd_error;
  }
#else //手动实现一个lock
  int rc;
  struct timespec cur, dur;

  /* Try to acquire the lock and, if we fail, sleep for 5ms. */
  while ((rc = pthread_mutex_trylock (mtx)) == EBUSY) {
    timespec_get(&cur, TIME_UTC);

    if ((cur.tv_sec > ts->tv_sec) || ((cur.tv_sec == ts->tv_sec) && (cur.tv_nsec >= ts->tv_nsec)))
    {
      break;
    }

    dur.tv_sec = ts->tv_sec - cur.tv_sec;
    dur.tv_nsec = ts->tv_nsec - cur.tv_nsec;
    if (dur.tv_nsec < 0)
    {
      dur.tv_sec--;
      dur.tv_nsec += 1000000000;
    }

    if ((dur.tv_sec != 0) || (dur.tv_nsec > 5000000))
    {
      dur.tv_sec = 0;
      dur.tv_nsec = 5000000;
    }

    nanosleep(&dur, NULL);
  }

  switch (rc) {
    case 0:
      return thrd_success;
    case ETIMEDOUT:
    case EBUSY:
      return thrd_timedout;
    default:
      return thrd_error;
  }
#endif
}

 背景

linux下线程通信方法:互斥锁,条件变量,信号量,读写锁

 

 

 

 

 

互斥锁

同一时刻只允许一个线程执行一个关键部分的代码

linux下pthread互斥锁函数

linux下互斥锁类型

 

 

 

按照系统分类直接调用系统下线程处理模块函数:
线程销毁 void mtx_destroy(mtx_t *mtx) 
线程加锁  int mtx_lock(mtx_t *mtx)
尝试锁 int mtx_trylock(mtx_t *mtx)
解锁 int mtx_unlock(mtx_t *mtx)
 

条件变量

 
 
利用线程间共享全局变量进行同步的一种机制。条件变量上的基本操作有:触发条件(当条件变为 true 时);等待条件,挂起线程直到其他线程触发条件
1.创建条件变量   pthread_cond_init(cond, NULL)
2.销毁条件变量   pthread_cond_destroy(cond)
3.激活等待该条件的线程(多个等待线程按顺序激活一个) pthread_cond_signal(cond)
4.广播激活所有等待条件线程 pthread_cond_broadcast(cond)
5.自动解锁互斥量,并等待条件变量触发 pthread_cond_wait(cond, mtx)     pthread_cond_wait()  函数一进入wait状态就会自动release mutex
                                                                                                                       pthread_cond_wait()通过(返回)时,该线程又自动获得该 mutex
6.超时条件触发 pthread_cond_timedwait
 

线程操作

1.线程创建:pthread_create

 

 

第一个参数为指向线程标识符的指针, 在程序中我们传递p的地址进去.
第二个参数为线程的属性. 默认传递NULL就可以. 线程的属性有很多, 比如可以设置线程调度的优先级, 比如可以设置线程栈的大小. 可以看看这篇博客
第三个参数是线程要执行的函数指针. 从函数原型上看, 这个函数的类型只能是void *
第四个参数是函数的参数. 从函数原型上看, 参数的类型只能是void *. 但我们知道void *类型是可以转换为其他类型的, 所以在这个函数内部进行类型转换即可. 如果有多个参数需要传递, 就定义一个结构体

2.线程等待pthread_join(thr, &pres)

...

 

posted @ 2022-03-25 18:36  Aemnprsu_wx  阅读(96)  评论(0编辑  收藏  举报