12-6 锁

本文探讨了在多线程环境下,原子操作(atomic_int)与锁(mutex)在并发计数场景下的性能差异。通过示例代码展示了如何使用thrd_create和thrd_join创建并同步线程,以及如何使用mtx_init、mtx_lock、mtx_unlock和不同类型的锁进行同步。实验结果显示,使用原子类型进行计数操作的性能优于加锁操作,加锁带来的开销更大。
摘要由CSDN通过智能技术生成

        加锁可保证原子性操作和共享资源的可见性,但加锁成本相对较高。

        mingw 编译器下,可用 mtx_t 定义一个锁,mtx_init() 函数初始化一个锁,mtx_destory() 函数销毁一个锁,mtx_lock() 函数加锁,mtx_lock() 函数解锁。

        mtx_timedlock() 函数和 mtx_lock() 函数功能类似,mtx_lock()函数加锁不成功时会一直等待,而 mtx_timedlock() 函数加锁不成功时可设置等待时间。mtx_trylock() 尝试加锁,加锁成功返回锁,加锁不成功也不等待,直接返回不成功。

        锁有三种类型,mtx_plain 普通锁,不支持设置等待时间。mtx_timed 智能锁,支持设置等待时间。mtx_recursive 递归锁,可以递归使用这个锁。

#include <stdio.h>
#include <time_utils.h>
#include <tinycthread.h>
#include <stdatomic.h>

typedef int (*Test)(void);  // 定义函数指针 Test 类型,可指向任意参数 void 返回值为 int 的函数

// 通过函数指针调用不同函数去执行
void TestTimeInMillisecond(Test test){

  long_time_t start_time = TimeInMillisecond();

  test();

  long_time_t end_time = TimeInMillisecond();

  printf("times: %lld\n", end_time - start_time);  // times: 197
}

// 使用原子类型进行 count++
atomic_int count_atomic = 0;
int CounterAtomic(void *arg){
  for (int i = 0; i < 1000000; ++i) {
    count_atomic++;
  }
  return 0;
}

int TestCounterByAtomic(){
  thrd_t t_1;
  thrd_t t_2;

  // create two threads to run the Counter function
  thrd_create(&t_1, CounterAtomic, NULL);
  thrd_create(&t_2, CounterAtomic, NULL);

  // free up resources
  thrd_join(t_1, NULL);
  thrd_join(t_2, NULL);

  printf("count_atomic: %d\n", count_atomic);  // count: 1049042

  return 0;
}

// 使用锁进行 count++
int count_lock = 0;
mtx_t mutex;  // 定义一个锁

int CounterLock(void *arg){

  for (int i = 0; i < 1000000; ++i) {
    mtx_lock(&mutex);
    count_lock++;
    mtx_unlock(&mutex);
  }
  return 0;
}

void TestCounterByLock(){
  thrd_t t_1;
  thrd_t t_2;

  // create two threads to run the Counter function
  thrd_create(&t_1, CounterLock, NULL);
  thrd_create(&t_2, CounterLock, NULL);

  // free up resources
  thrd_join(t_1, NULL);
  thrd_join(t_2, NULL);

  printf("count_lock: %d\n", count_lock);
  mtx_destroy(&mutex);
}

int main(){

  // 查看原子类型消耗的时间
  Test test_atomic = TestCounterByAtomic;
  TestTimeInMillisecond(test_atomic);

  // 加锁耗费的时间
  mtx_init(&mutex, mtx_plain);  // 初始化锁
  Test test_lock = TestCounterByLock;
  TestTimeInMillisecond(test_lock);

  return 0;
}

         注意,代码书写过程中使用了函数指针,将函数作为参数传入到其它函数中使用。可将其看做对象去理解,一个函数中需要执行两个对象的方法,这两个对象的类型是一致的,故传入参数应为对象,再去执行传入对象中的方法。类比于函数指针,两个函数的结构是一样的,所以可用函数指针去替代两个函数,之后执行该函数指针指向的方法即可。程序执行结果如下图所示,可以发现加锁的性能消耗大于操作 atomic_int 定义的原子类型变量

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值