合租的室友在帮他的一同学做百度笔试题,并拉上我和另一室友一起做。第一题是关于线程安全的:
现代的处理器提供了compare-and-swap原子操作:
int compare_and_swap(int * pv, const int cv, const int nv);
即比较*pv与cv,如果相等,则把*pv值替换为nv并返回*pv原值,否则返回*pv的值。
请利用上述原子操作实现如下操作:
int inc_if_gt_zero(int * pv);
即如果*pv > 0,则把*pv加1并返回修改后的*pv,否则返回*pv。
结果要线程安全且不使用锁、信号灯、互斥量、临界区或类似机制。
由于看过一些java多线程方面的书籍,也比较熟悉,JDK5的AtomicXXX中incrementAndGet等操作的内部实现也用到compare-and-swap这一原子操作。 下面是我的代码:
int inc_if_gt_zero(int * pv) {
while (true) {
int c = *pv;
if (c <= 0) return c;
int v = compare_and_swap(pv, c, c+1);
if (c == v) {
return c+1;
}
}
}
主要思想是在对pv进行加1操作之前,看它的值有没有改变,没有改变就执行加1操作,否则重试。Doug Lea的经典著作《Concurrent Programming in Java》将这种方法称之为"乐观重试",《Concurrent in Practice》书中则称之为"无等待算法"。对我来说这显而易见,但是我的两个室友却不同意。我的两个室友都是做C++的,都是我的同学,不妨称之为室友A和室友B。室友A直觉上感觉不靠谱,但是找不出原因,室友B则认为完全不对。我没能说服他们,我发现争议的焦点在于对线程安全的理解上,室友A做过多线程编程,他从锁机制的角度来考虑线程安全,因而才对"乐观重试"的方法感觉不靠谱,室友B则基本没有做过,认为对上题来说,输入为2时,必须输出就为3,对他来说,下面的单线程程序就是正确的:
int inc_if_gt_zero(int * pv) {
int c = *pv;
if (c <= 0) return c;
*pv = ++c;
return c;
}
当时我对线程安全的概念也一直没有好好梳理,也无法用语言清晰的表达出我的思想。经过一晚上的思考,思路终于有些清晰了。线程安全的一个重要规则是"as-if-serial"规则,也就是多个线程同时执行操作(在语义上是原子性的操作),看起来就像在单个线程顺序执行这些操作一样。具体来说,以上面的例子为例,假设n个线程,分别表示为T1,T2,...和Tn,同时执行inc_if_gt_zero操作,pv的初始值为1,那么对于线程安全的程序来说它必须保证两个结果:
- n个线程执行完毕后,它必须和单个线程中顺序执行n个inc_if_gt_zero操作之后的内存效果一样,也就是pv的值必须为n+1。
- as-if-serial规则虽然保证多个操作看起来像在单线程中执行一样,但并不保证它们执行的顺序。对于该例子,执行的结果可能是按T1,T2,...Tn的顺序,也可能是按Tn,Tn-1,...T1的顺序,最多只可能为n!种顺序。如果按照T1,T2,...Tn的顺序的操作执行,T1,T2,...Tn的inc_if_gt_zero分别返回2,3,...n+1,如果按Tn,Tn-1,...T1的顺序,T1,T2,...Tn的inc_if_gt_zero分别返回n+1,n,...1。可以得知,线程T1,T2,...Tn的inc_if_gt_zero的返回结果必定是2,3,...,n+1的一个排列,但到底是哪个排列是不确定的。这里并不需要保证inc_if_gt_zero返回时pv的值和返回值相同。
对于该程序的单线程版本,它明显可能违背结果1,最终pv的值可能小于n+1,当然也违背结果2,多个线程执行的结果也可能出现重复的值。对于该程序的关键是保证判断c是否大于0的语句和将pv的值加1的语句之间不能被别的线程给打断,这可以通过锁机制来实现,也可以通过上面说的乐观重试机制来实现,这多少有些类似数据库中的悲观锁和乐观锁。
最后要注意的是,对于该程序的乐观锁版本,如果将最后一句"return c+1",改成"return *pv"是有问题的,这在单线程程序中是正确的,在多线程中这时pv的值可能不再等于c+1了,这导致T1,T2, ...Tn的inc_if_gt_zero可能返回重复值。
分享到:
相关推荐
《百度历年笔试题解析》 在信息技术领域,面试与笔试是评估求职者技能的重要环节,尤其是对于技术型岗位,如百度这样的互联网巨头,其历年笔试题不仅反映了公司的技术导向,也揭示了当前行业关注的技术热点。本文将...
【百度笔试题】中的知识点主要涉及三个方面:编程题、算法题和系统设计。下面将分别对这三个方面进行详细的解析。 1. **编程题** 这道编程题要求编写一个函数`is_include(char *a, char *b)`,判断字符串`b`的所有...
嵌入式软件笔试题合集嵌入式软件笔试题合集嵌入式软件笔试题合集嵌入式软件笔试题合集嵌入式软件笔试题合集嵌入式软件笔试题合集嵌入式软件笔试题合集嵌入式软件笔试题合集嵌入式软件笔试题合集嵌入式软件笔试题合集...
从给定的百度公司笔试题中,我们可以提炼出多个IT领域的知识点,主要集中在数据结构、算法、编程语言特性以及操作系统原理上。以下是对这些知识点的详细解析: ### 数据结构与算法 1. **排序算法的特性**:题目...
【百度笔试题】是应聘者在申请百度职位时可能会遇到的测试内容,涵盖了一系列的编程基础知识,主要包括排序算法、多线程同步、内存管理、网络协议、数据结构和操作系统等主题。下面是对这些知识点的详细解释: 1. *...
总而言之,“百度最全笔试题”提供的是一场全面的Java技术考验,涵盖了从基础到进阶的各个层面。通过深入学习和实践这些题目,Java程序员可以不断提升自己的专业技能,为在竞争激烈的IT行业中脱颖而出做好充分准备。
"腾讯百度笔试题"集合了这两家互联网巨头历年来的技术笔试题目,覆盖了多个关键领域,如C语言、数据结构和操作系统等。这些知识点是计算机科学和技术专业学生以及求职者必须掌握的基础。 首先,让我们深入探讨C语言...
C++面试题笔试题C++ 数据结构算法笔试题资料合集: 50个C、C++面试题.pdf C++ 数据结构、算法笔试题.docx C++基础面试题.docx C++开发工程师面试题库.docx C++技能测试试卷一及答案.docx C++技能测试试卷二及答案....
有txt格式的,有的是俺在网上搜的网页直接保存下来的。有的题目给出了参考答案,不过不一定正确。我当初笔试的是质量部的软开,笔试题附其中了,其余的更多是运维部的笔试题吧。
同步是为了避免数据竞争,确保线程安全。 3. 变量val在函数func中声明为静态,其内存地址位于已初始化数据段(A)。静态变量在程序执行前分配内存,生命周期贯穿整个程序。 4. 同一进程下的线程可以共享数据段(B...
文档“百度Java笔试题@www.java1234.com.doc”可能包含具体的题目和解题思路,对于准备此类笔试的考生来说,深入学习上述知识点,并通过做题实践来巩固,将大大提高通过笔试的可能性。同时,不断关注最新的Java技术...
【百度校园招聘笔试题 Baidu必备】:这篇文章的标题揭示了其主要内容,即与百度公司校园招聘相关的笔试题目。这些题目通常涵盖了计算机科学和技术领域的基础知识,包括但不限于算法、数据结构、编程语言、操作系统、...
中兴笔试题 中兴笔试题 中兴笔试题 中兴笔试题 v中兴笔试题 中兴笔试题 ...中兴笔试题 中兴笔试题 中兴笔试题 中兴笔试题中兴笔试题 中兴笔试题 中兴笔试题 中兴笔试题 中兴笔试题 中兴笔试题 中兴笔试题 中兴笔试题
java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 java笔试题 ...
很好的百度笔试题,想去百度的人可以做一下,预预热
【标题解析】:“08百度笔试题(北京)”指的是2008年百度公司在北京市进行的一次技术笔试,主要针对系统开发工程师等职位。题目旨在考察应聘者的编程能力、算法理解和系统设计思维。 【描述解析】:16号的百度北京...
大连华信去年的笔试题,可以给各位即将工作的同学一些参考
《百度校招面试笔试题解析》 在求职竞争激烈的今天,各大互联网...总的来说,百度的笔试题旨在寻找有深厚技术功底、良好问题解决能力的优秀人才。只有通过持续学习和实践,才能在竞争中脱颖而出,赢得心仪的工作机会。
从这个文件名可以推测,压缩包内可能包含的是一份或几份百度2013年校招移动开发工程师职位的笔试题目。这些题目可能以PDF、DOC或TXT等形式存在,内容可能包括选择题、填空题、编程题等,旨在测试考生的移动开发技术...