Blog

权衡式思维

Content #

权衡式思维(trade-off thinking)它是由稀缺所引发的一种思维方式。在稀缺状态下,因为所有没有被满足的需要俘获了我们的大脑,以致我们开始对之念念不忘,开始产生决策难题。

稀缺心态一旦出现,我们就必须应对心智资源更加紧缺的问题。稀缺,不仅仅会令我们入不敷出,不知如何分配资源,而且还会让我们在生活的其他方面手足无措。稀缺会使人变笨,变得更加冲动。我们不得不在流体智力和执行控制力被减弱的情况下,依靠更为有限的脑力去勉强度日。生活,就这样变得举步维艰起来。

稀缺不仅提高了失误的成本,也为人们创造了更多机会去犯下错误、做出不明智的选择。稀缺状态下,将事情做对做好会变得更加艰难,因为无论是忙碌之人的时间,还是贫穷之人的金钱,都必须在十分有限的范围内精打细算。

Viewpoint #

From #

《稀缺》 塞德希尔·穆来纳森 2014

稀缺的本质就是没有余闲

稀缺的本质就是没有余闲

Content #

把东西装进行李箱,是对资源管理问题的最好比喻。我们每个人都有一个时间箱,要在里面装上工作、休闲和与家人共度的时光。我们也都有一个金钱箱,要在里面装上住房、服饰和其他所有支出。资源的稀缺和富足,会改变我们装箱的方式。如果没有余闲存在,我们在装箱时就不得不进行权衡。可见,稀缺的本质就是没有余闲。

余闲(slack) 就是我们在拥有很大空间,不存在稀缺心态时的产物,也是我们在资源丰富时进行资源管理的特定方式。

当大行李箱和小行李箱的主人在装箱时停下手来,每个人都有尚未被装进行李箱的物品时,二者就会表现出不同行为:对于小行李箱的主人而言,许多十分重要的东西装不进行李箱的情况会唤起他们的关注和焦虑。就这样,他们会对这些装不进去的东西产生管窥心态,会不由自主地想:“难道我不能重新整理一下箱中的物品,然后将这些东西也塞进去吗?”装箱这件事俘获了他们的注意力,因为装不进行李箱里的物品的确十分重要。但当大行李箱的主人停下手来时,就说明没有装进行李箱的物品确实没那么重要——装上也好,不装也罢。大行李箱的主人之所以会产生余闲,是因为他们并不那么在意装箱这件事情。

这样一来,低效和浪费就会产生。当我们拥有很多空闲时间时,就会无所事事,然后时间就这样被耗尽了。从各项工作的间歇中挤出来的零散时间,加在一起也会有好几个小时。原本一天可以工作16个小时,但结果只做了6个小时的事情。我们常常会用一周时间去完成一项本来只需要用两天时间就能完成的事。而且,我们现在指的并不是那些你明确认为“没事可做”的时间段,而是那些没有被你合理利用的时间。当我们拥有一些自由时间时,就会散漫地将其一点点浪费掉。当我们不费什么力气就能赚到钱时,就会购买一些之后会被弃置一旁的物品。就这样,我们浑浑噩噩地过着日子,不知道时间是怎么渐渐流逝的;橱柜里装满了我们永远不会去吃的汤罐头,而自助式仓库里还存放着一大堆早就被我们忘却了的东西。

Viewpoint #

余闲太多,会无所事事,浪费资源。余闲太少,会产生管窥心态,智力下降。

From #

《稀缺》 塞德希尔·穆来纳森 2014

意志力不过是去学习如何控制注意力和想法

棉花糖实验 #

能够成功抵制棉花糖诱惑的孩子,是因为他们将注意力转移到了别处——他们没有盯着棉花糖,想着将其吃到嘴里,而是在想其他事情。他们想办法不去关注棉花糖,这样就不用与想吃的欲望做直接抗争了。正如米歇尔所说的,“一旦你意识到意志力不过是去学习如何控制注意力和想法时,就能开始提高自身的意志力了”。

Viewpoint #

意志力控制不了,注意力与想法是可以控制的。

From #

《稀缺》 塞德希尔·穆来纳森 2014

因稀缺而心神不宁

Content #

想像你的汽车出了问题,候车费用需要300美元,你如何做决定?再假设维修费用是3000美元,又会怎样?

富有的实验对象面对此种稀缺并不会产生过多的想法——他们面对3000美元和面对 300美元时的心情一样,测验成绩都不错;而贫穷的实验对象,其测试成绩却会与之前相比差很多。仅仅是稍稍涉足稀缺问题的地盘,他们的智商就会一下子呈现出很大幅度的下降。他们因稀缺而心神不宁,而其流体智力的水平也会随之跌落。

我们的研究显示,只是单纯地引起低收入者对财务的顾虑,就会严重地影响他们的认知表现能力,其严重性甚至超越了失眠所造成的影响。

同一个人在将注意力集中于稀缺问题时,他的IQ分数就会比不存在稀缺问题时要低。这一点非常重要。如果车辆的维修费用不高,那么穷人的成绩就会与富人一样好,因为此时稀缺问题并没有显现出来。这和与生俱来的认知能力无关。正如电脑同时运行着多个应用程序时,中央处理器就会降低运转速度一样,穷人在此时会表现得更差一些,因为他们的一部分带宽正在想着其他事情。

Viewpoint #

GTD里讲的心若止水的状态很重要。还要解决沉没成本问题。

From #

《稀缺》 塞德希尔·穆来纳森 2014

前摄干扰实验

Content #

实验对象要找到重点标注的词语(这个例子中是STREET一词)。找到并点击之后,会出现新的字母拼图,然后接着再去找下一个词语。

寻找重点标注的词语

另一组实验对象接受了相同的任务,但要找的词语有些许不同: 寻找偶数位置的词语

对于两组实验对象来说,列表中位于偶数位置的词语是相同的。第一组实验对象的奇数位词是中性词,而第二组实验对象的奇数位词则具有一定的吸引力:街道(STREET)换成了蛋糕(CAKE),图片(PICTURE)换成了甜甜圈(DONUT),以此类推。之后,我们对实验对象需要多长时间找到相同的词语进行了观察(这里说的相同词语指的就是那些两组通用的偶数位中性词)。

对于大多数实验对象来说,改变奇数位词并没有什么效果;而对于节食者来说则有所不同。节食者刚刚找过DONUT一词后,需要用比其他人多30秒钟的时间才能找到CLOUD一词。总体来讲,节食者并不比别人迟钝。如果CLOUD一词之前出现的是PICTURE一词,那么他们找到CLOUD的速度就会与别人一样快。关键区别就在于 DONUT这个词上,这个影响是显而易见的。这就是心理学家所谓的“前摄干扰”现象。节食者看到甜甜圈一词后,会将这一概念置于思想的中心。非节食者不过是简单地去寻找这个词语,找到这个词语,然后继续下一项任务。而节食者则没那么容易放下与这个词语相关的想法,继续执行任务。就算已经开始寻找下一个词CLOUD,DONUT的影子还是会像呼啸而过的火车一样,把他们的注意力带走。而当你心里想着其他事物时,自然就很难会找到CLOUD一词。

前摄干扰(Proactive interference) 当我们心里想着其他事物时,就会将其置于思想的中心,而产生忽略行为。

From #

《稀缺》 塞德希尔·穆来纳森 2014

注意力的自上而下处理和自下而上处理

Content #

内源性思考(internal thought) 即便在大脑中重复一连串数字这种小事也会对人的总体认知能力产生深远影响。

“自上而下”处理指的是思想会对所关注的事物进行有意识的选择;而“自下而上”处理则指的是注意力会被很难为我们所控制的刺激所俘获。

有一个例子讲的是与食物有关的词汇能俘获饥饿之人的注意力。我们每个人都对这种感觉再熟悉不过:任何时候,一个快速的动作或突发的声音都能将我们的注意力从正在做的事情上吸引开来。

一种特别值得注意的分心形式,它并不需要外部干扰因素的影响就会存在,那就是“神游”。大脑处于休息状态时,默认网络会将我们的思想从正在做的事情上拉走,而我们根本意识不到。“神游”名副其实,即在意识的控制之外,我们的心神会四处游走。

由此可见,虽然我们有能力直接控制大脑活动,但有些时候它们还是会失去控制。对于铁道旁边学校里的学生而言,在自下而上分心事物存在的情况下,保持专注的能力就取决于大脑当时的工作量,取决于其“装载”了多少东西。行为和神经成像研究显示,在大脑装载量较多时,引起分心的事物一旦出现,分心程度以及大脑的活动量都会有所提升。

而且,自上而下的注意力无法阻止自下而上的侵入。比如,在热闹的聚会场所中,当房间的另一边有人叫你的名字时,无论你正多么专心致志地关注某件事情,你的注意力都会有所转移。

Viewpoint #

神游是无法避免的。

From #

《稀缺》 塞德希尔·穆来纳森 2014

带宽指的是心智功能中哪两个元素

“带宽”指的是心智功能中哪两个元素? #

第一类元素可以被宽泛地称为“认知能力”,它是我们解决问题、获得信息、进行逻辑推理等能力背后的心理学机制。认知能力中最突出的就是“流体智力”,即在进行抽象思维和推理时,在无须特定学习或体验的情况下解决问题的能力。

第二类元素是“执行控制力”,其作用存在于我们管理自身认知能力的过程中,包括计划、关注、发起并抑制行为和控制冲动等。执行控制力就像中央处理器一样,是我们进行日常活动的必要能力,可以决定我们的专注力和转移注意力的能力、从记忆中提取信息的能力、同时处理多项任务的能力以及自我监督的能力。

认知能力和执行控制力拥有多个层面和丰富的细节。稀缺对以上两者都会产生影响。

Viewpoint #

“带宽"是通俗的说法,比较形象。

From #

《稀缺》 塞德希尔·穆来纳森 2014

亚马逊的Prime会员是如何体现其客户至尚原则

Question #

亚马逊的Prime会员是如何体现其客户至尚原则的?

Answer #

2017 年 7 月贝佐斯在给股东的年度公开信中再一次强调了“客户至尚”的重要性,或许你能从中一窥究竟。公开信里大体是这样说的:

有很多方法可以成为做生意的核心。企业可以以竞争对手为核心,也可以以产品为核心。企业还可以聚焦于技术,或者以业务模式为核心等等。但在我看来,以客户为中心是最为有利的方式。

为什么呢?以客户为中心的方法有很多优点。其中很大的一个优点是:客户总是
非常不满足。即便他们说他们很满足,公司业务很好。客户总是想要更好的东西,
甚至他们都没有意识到这一点。遵循着让客户满意的意图将驱使企业代表客户去
发明和创造。没有客户曾经要求亚马逊创建 Prime 会员计划,然而我们发明了
这项服务。最后确实证明客户是想要这个计划的。类似这样的例子,我可以列举
很多。

这封信里提到了亚马逊的 Prime 会员,这是一项定价 95 美元的年收费服务项目。这一项目的性价比很高,用户可以享受到包括免费隔日送达货物、免费视频等多项便利服务。

该项目在初推之时,亚马逊内部并不是一片和谐,很多人都提出了反对意见。反对 Prime 会员计划有很多原因,其中比较重要的有两点。

第一点是这个计划成本昂贵。亚马逊做这个生意,非但不能赚到钱,还可能赔进去很多钱。比如说隔日免费寄送这项服务,用户每年只要下 4 单,邮费就超过 95 美元了。如果用户购买较多,亚马逊就会赔本。

第二点是这一项目需要收取年费,用户是否愿意为此买单,也是未知数。万一投入大量成本去开发,用户却不买账,那么会前功尽弃。

贝佐斯在推行项目之初,问了团队一个问题:“如果你是客户,是否愿意掏钱去享受这种服务?” 如果回答是肯定的,那么哪怕亚马逊会为此付出许多代价,甚至不能短期获利,这项服务也值得推出。

急客户所需,想客户所想,才是“客户至尚”的基本体现。坚持这样的理念,客户便会越来越愿意在亚马逊上消费,最后的规模效应才会形成良性循环。团队的回答当然是正面的,于是项目得以顺利推行。事后的发展印证了贝佐斯的想法。 Prime 会员制度推行之后,亚马逊上的购物量迅速增加,亚马逊的会员们对两天内送达这一服务表现出极大的热情。因为制度的推出,亚马逊迅速战胜了 eBay 和沃尔玛这样的传统零售商。

亚马逊固然没有从邮费上赚到钱,但其规模效应带来的收入却远远大于在邮费上的支出。这种规模效应的结果是:亚马逊的各方面都得到提升,客户对亚马逊的忠诚度也极大地提高了。

贝佐斯多次引用这个故事,告诉员工,也告诉亚马逊的客户与投资人,“客户至尚”这一准则对于亚马逊到底意味着什么。

Viewpoint #

From #

019 | 亚马逊领导力准则之客户至尚

信号量的实现

信号量的实现 #

信号师的实现需要三个问题:等待、互斥、唤醒(即重新激活等待的代码执行流)。

这就需要一种全新的数据结构来解决这些问题。根据上面的问题,这个数据结构至少需要一个变量来表示互斥,比如大于 0 则代码执行流可以继续运行,等于 0 则让代码执行流进入等待状态。还需要一个等待链,用于保存等待的代码执行流。

这个数据结构的实现代码如下所示。

#define SEM_FLG_MUTEX 0
#define SEM_FLG_MULTI 1
#define SEM_MUTEX_ONE_LOCK 1
#define SEM_MULTI_LOCK 0
//等待链数据结构,用于挂载等待代码执行流(线程)的结构,
//里面有用于挂载代码执行流的链表和计数器变量,这里我们先不深入研究这个数据结构。
typedef struct s_KWLST
{
    spinlock_t wl_lock;
    uint_t   wl_tdnr;
    list_h_t wl_list;
}kwlst_t;
//信号量数据结构
typedef struct s_SEM
{
    spinlock_t sem_lock;//维护sem_t自身数据的自旋锁
    uint_t sem_flg;//信号量相关的标志
    sint_t sem_count;//信号量计数值
    kwlst_t sem_waitlst;//用于挂载等待代码执行流(线程)结构
}sem_t;

搞懂了信号量的结构,我们再来看看信号量的一般用法,注意信号量在使用之前需要先进行初始化。这里假定信号量数据结构中的 sem_count 初始化为 1, sem_waitlst 等待链初始化为空。

使用信号量的步骤: 第一步,获取信号量。

  1. 首先对用于保护信号量自身的自旋锁 sem_lock 进行加锁。
  2. 对信号值 sem_count 执行“减 1”操作,并检查其值是否小于 0。
  3. 上步中检查 sem_count 如果小于 0,就让进程进入等待状态并且将其挂入 sem_waitlst 中,然后调度其它进程运行。否则表示获取信号量成功。当然最后别忘了对自旋锁 sem_lock 进行解锁。

第二步,代码执行流开始执行相关操作,例如读取键盘缓冲区。第三步,释放信号量。

...

自旋锁算法的实现

自旋锁算法的实现 #

自旋锁算法看似很好,但是想要正确执行它,就必须保证读取锁变量和判断并加锁的操作是原子执行的。否则,CPU0 在读取了锁变量之后,CPU1 读取锁变量判断未加锁执行加锁,然后 CPU0 也判断未加锁执行加锁,这时就会发现两个 CPU 都加锁成功,因此这个算法出错了。

怎么解决这个问题呢?这就要找硬件要解决方案了,x86 CPU 给我们提供了一个原子交换指令,xchg,它可以让寄存器里的一个值跟内存空间中的一个值做交换。例如,让 eax=memlock,memlock=eax 这个动作是原子的,不受其它 CPU 干扰。

下面我们就去实现自旋锁,代码如下所示。

//自旋锁结构
typedef struct
{
    //volatile可以防止编译器优化,保证其它代码始终从内存加载lock变量的值
     volatile u32_t lock;
} spinlock_t;
//锁初始化函数
static inline void x86_spin_lock_init(spinlock_t * lock)
{
     lock->lock = 0;//锁值初始化为0是未加锁状态
}
//加锁函数
static inline void x86_spin_lock(spinlock_t * lock)
{
    __asm__ __volatile__ (
    "1: \n"
    "lock; xchg  %0, %1 \n"//把值为1的寄存器和lock内存中的值进行交换
    "cmpl   $0, %0 \n" //用0和交换回来的值进行比较
    "jnz    2f \n"  //不等于0则跳转后面2标号处运行
    "jmp 3f \n"     //若等于0则跳转后面3标号处返回
    "2:         \n"
    "cmpl   $0, %1  \n"//用0和lock内存中的值进行比较
    "jne    2b      \n"//若不等于0则跳转到前面2标号处运行继续比较
    "jmp    1b      \n"//若等于0则跳转到前面1标号处运行,交换并加锁
    "3:  \n"     :
    : "r"(1), "m"(*lock));
}
//解锁函数
static inline void x86_spin_unlock(spinlock_t * lock)
{
    __asm__ __volatile__(
    "movl   $0, %0\n"//解锁把lock内存中的值设为0就行
    :
    : "m"(*lock));
}

上述代码的关键点在于 xchg 指令,xchg %0, %1 。其中, %0 对应 “r”(1),表示由编译器自动分配一个通用寄存器,并填入值 1,例如 mov eax,1。而 %1 对应"m"(*lock),表示 lock 是内存地址。把 1 和内存中的值进行交换,若内存中是 1,则不会影响;因为本身写入就是 1,若内存中是 0,一交换,内存中就变成了 1,即加锁成功。

...