12-8 副作用与纯函数

1. 副作用

        函数副作用:指当调用函数时,除了返回函数值之外,还对主调用函数产生附加的影响。例如修改全局变量(函数外的变量)或修改参数。

        表达式副作用:在表达式求值过程中,需要获取变量的值,但并不改变这些变量的值,这样的表达式称为无副作用的表达式。一个表达式在求值过程中,对使用的变量不但引用,对它们的值还加以改变,这样的表达式称为有副作用的表达式。例如 count++,表达式获取的是 count 值,但在获取过程中对 count 变量的值进行了加 1 操作,故此表达式是有副作用的表达式。

        纯函数:输入输出数据流全是显式的。 显式的意思是,函数与外界交换数据只有一个唯一渠道——参数和返回值。函数从函数外部接受的所有输入信息都通过参数传递到该函数内部。函数输出到函数外部的所有信息都通过返回值传递到该函数外部。

        此外,还有非纯函数引用透明,详细可见链接:https://www.cnblogs.com/snandy/archive/2011/08/14/2137898.html

2. 缩小副作用范围,解决线程安全问题

        从表达式副作用角度考虑 12-3 小节的 count++ 问题,若 count++ 副作用修改的 count 变量不是其他线程的变量,则不存在线程安全问题。故将 count 定义为局部变量,而并非全局变量。代码如下所示:

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

int Counter(void *arg){
  int local_count = 0;
  for (int i = 0; i < 1000000; ++i) {
    local_count++;
  }

  return local_count;
}

void TestCounterByThread(){
  thrd_t t_1;
  thrd_t t_2;

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

  int count = 0;
  int result;

  // free up resources
  thrd_join(t_1, &result);
  count += result;
  thrd_join(t_2, &result);
  count += result;
  
  printf("count: %d", count);  // count: 2000000
}

        这种方法的解决思路与 _Thead_local,tss_t 类似,即从根本上杜绝线程安全问题的发生。线程之间不再享有共享资源,每个线程不操作其他线程的变量,仅操作线程内部的变量

        以 count++ 问题为例,该问题的需求是启用两个线程,将主线程的 count 变量加 20w 次。可以设置锁等操作,将两个线程并发执行,修改主线程变量最终得到 20w。也可以在每个线程内部加 10w 次,将两个线程的结果进行合并,进而将主线程 count 变量进行 20w 次的相加。核心仍为,不操作主线程的变量,仅操作线程内部的变量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值