精华内容
下载资源
问答
  • 一个工程项目中,我们需要建立若干个任务来完成... ①给任务分配一个优先级  在ucosii中,V2.86之前的版本支持的任务64,V2.86开始支持256个任务。  #define APP_TASK_LED_PRIO (任务优先级N)  ②给任...

      在一个工程项目中,我们需要建立若干个任务来完成目标。在ucosii中,只有任务在建立之后,才能被系统管理。

      在ucosii中,建立一个新的任务只需要简单的3步:

      ①给任务分配一个优先级

       在ucosii中,V2.86之前的版本支持的任务数是64,V2.86开始支持256个任务。

       #define  APP_TASK_LED_PRIO    (任务优先级N)

      ②给任务分配一个栈空间

         #define APP_TASK_LED_STK_SIZE   128

       static OS_STK AppTaskLEDStk[APP_TASK_LED_STK_SIZE];

      ③创建任务 OSTaskCreate() or OSTaskCreateExt()

      OSTaskCreateExt(APP_task_LED,

    (void *) 0,
    (OS_STK*)&AppTaskLEDStk[APP_TASK_LED_STK_SIZE - 1],
    APP_TASK_LED_PRIO,
    APP_TASK_LED_PRIO,
    (OS_STK *)&AppTaskLEDStk[0],
    APP_TASK_LED_STK_SIZE,
    (void *) 0,
    OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR
    );

      

    转载于:https://www.cnblogs.com/xiaokangkp0602/p/9088253.html

    展开全文
  • 一个好的项目经理

    千次阅读 热门讨论 2015-07-29 10:49:14
    时光回转,师哥让写的时候我只写了这四条,草草交差: 1、会让自己更积极,对比当组员的时候,目光只是放在自己的模块的任务量上,而不是整个项目。...怎样协调工作,合理分配。以及和其他系统的交流,包括接口等

              记得那是在3.0的时候当新生组长的时候,师哥让每个组长写的一个东西,时间过去很久了,最近又有很多感触,翻出来,再品味……

     

    时光回转,师哥让写的时候我只写了这四条,草草交差:

              1、会让自己更积极,对比当组员的时候,目光只是放在自己的模块的任务量上,而不是整个项目。

              2、会让自己认识到以前的自己是在浪费了多少资源和多少时间。

              3、从我自身的角度,让我的脾气收敛了许多,在说话做事之前都要想想这么说是不是合理,说话的艺术。

              4、与更多人交流的机会,和自己的组员,了解组里的人哪些是大牛,哪些人需要帮助。怎样协调工作,合理分配。以及和其他系统的交流,包括接口等问题,怎样更清晰简洁的表达自己的需求,来让别人满足我们的需求,为我们提供服务。

     

              PM,不是你技术群雄,可以帮组员解决任何的难题,不光是项目管理技术本身,例如生命周期、风险分析技术、范围管理技术等。在软技能、领导力或者是影响力方面,也隐含了许多的价值观,这才是项目管理更高层次的东西。

     

              现在我还是想问:你认为一个项目经理应该具备的是什么?管理人的能力、协调能力……

              I want to say……

     

    项目经理有必要高度重视项目文档吗?

              其实,如果项目经理不高度重视项目文档,本身就不是一个合格的项目经理,因此,这并不是项目文档是否重要的问题,而是如何按照软件规范做好文档管理工作。开始的工作就是让各组长指定组内的七天计划,做好需求分析、了解未完成业务,其实这些都是需要整理成文档形式下发的,在项目过程中的每次任务完成情况的汇报,以及项目结束后的总结和交接工作,都是需要是以文档的形式来传达的。所以,真人的对待自己写的每一份文档,按照规范来书写自己的程序人生.所以呢,不是项目文档是否重要,而是如何按照软件规范做好文档管理工作。。文档毫无疑问比代码重要的多。而且在3.1中属人员实习交接工作尤为严重,让一个组长最痛苦的事情莫过于:当一个重要成员半途离开项目组时,才发现他根本没留下任何可用的文档。天下没有不散的宴席,项目组的成员也是在动态调整中,文档就是成员之间交接的重要工具。所以,一些组长很容易陷入“重技术实现,轻文档”的误区。他们总是认为项目实施时间紧迫,为了节省时间,可以在项目收尾阶段突击写文档。要是项目周期稍长,到了最后,成员不会太清清楚楚每个实现细节了。没有文档的项目铁定是一个失败的项目。3.1的文档不是很完善,不是实时的更新,好在一些文档都还有,稍微有些混乱,但还不至于严重影响到了开发。

           

              如果我是一个项目经理,会这么做:

    1、我会高度重视项目文档,因为项目文档是与上司沟通的主要方式

    2、我会高度重视项目文档,因为项目文档时与下属沟通的重要方式。与下属沟通不畅,项目质量就难以保证。

    3、我要通过项目文档的重视及组织实施,使项目组的每一位成员(包括我)在一定程度上都是可替换的,是整个项目组的风险降到最低。

     

    项目经理掌握整个开发生命周期

              阶段:启动、规划、执行、监控、收尾

              启动:明确人和目的

              规划(做计划):粗略以及详细,渐进明细一步一步完善,实时调整。

              执行:计划怎么样,有变动就修改计划,跟着计划走。

              监控:查看执行是否符合计划。

              收尾:整理所有资料和文档,为下一个项目迭代做准备。

     

              其实在3.1中整个生命周期都还不错,启动明确的每个人的职责,有专攻技术有专攻开发的。有一个整体的目标。接着在规定时限的情况下做好计划,我整体做好粗略的规划,每个小组长收集组内的具体计划。最重要的就是执行,大家执行的都还不错。但是在监控阶段做的不是很好,主要也是我的疏忽,各个小组长监控具体每个功能技术点,我来掌握全局,就是检查和反馈的不好,所以才会出了一点问题。

              3.1做的好的地方,除了监控阶段有点问题,最好的就是收尾工作了,总结了所有前人的优点以及做的不好的地方,扬长避短,总结经验,弥补不足,整理文档,遇到问题想解决方法解决问题。整个收尾工作(管理+技术分享)正在如火如荼的进行。

     

    沟通和整合

              3.1期间,有一个非常痛彻心扉的领悟,如果你是一个忙于具体细节的pM,那么你很可能会忽略项目的整体目标,或者说可能不是一个合格的项目经理。我把这些归结到沟通和整合中,具体的细节工作,都应该是交给下面的团队组长和成员去完成,项目经理负责整体的监控即可。也许你是3.1中的一员,在组长没有能及时和精确的汇报各个组的情况时,也许你会看到我穿梭在整个项目组中,也许有的时候我是在了解业务,但多数也同时了解的开发进度,这个时候,大方向也许就会不顾过来。一个人,该注重细节的时候就要注重细节,但是当你出在一个领导的位置上,要让下属去注重细节,自己宏观掌控最为重要。当然,沟通交流时非常重要的一件事情,无论是我也好,组长也罢,在带领一个团队的时候,一定要保证整个团队的团结力和凝聚力,说话做事的艺术非常重要,其实,做工作和项目都是一样,我们都是在给自己做,而不是为了完成一项任务,不同的心态去做一项任务结果绝对不一样。所以,这个时候我们的作用就启动了,让每一个人能体验到做项目的好处,明白这是在给自己做事情,而不是给任何一个人去完成任务。同时,要让每一个人都觉得自己不是在只敲一条线,要让他觉得这个项目是每一个人的,每一个人都从宏观上来学习整个项目,让所有人都有一种主人翁的态度。其实有了凝聚力和团结力,这些都不在话下。


              3.1,让我学会了遇到问题不要怕,我有一个大大的团队和一个非常靠谱的“靠山”,所有的问题都一定会解决……

              3.1,让我学会了作为一个团队的核心任何时候都不能倒下,在谁的面前都不能再是一个小女孩……

              3.1,让我学会了在一起奋斗加班的日子还能收获友谊……

              3.1,让我懂得了,原来我们可以这么优秀……


            感谢3.1的所有人和帮助过3.1的的所有人……



             

    展开全文
  • 1、任务分配、人力资源分配、时间分配要与工程进度相协调 在小型软件开发项目中,一个程序员能够完成从需求分析、设计、编码,到测试的全部工作。随着软件项目规模的扩大,人们无法容忍一个人花十年时间去完成一个...
    1、任务分配、人力资源分配、时间分配要与工程进度相协调
    在小型软件开发项目中,一个程序员能够完成从需求分析、设计、编码,到测试的全部工作。随着软件项目规模的扩大,人们无法容忍一个人花十年时间去完成一个需要十几个人年才能完成的软件项目。大型软件的开发方式必然是程序员们的集体劳动。由于软件开发是一项复杂的智力劳动,在软件开发过程中加入新的程序员往往会对项目产生不良影响。因为新手要从了解这个系统和以前的工作做起,当前正在从事这项工作的“专家”不得不停下手中的工作,抽出时间对他们进行培训。于是,在一段时间内,工作进度便拖后了。软件开发人数的增加将导致信息交流路径和复杂性的增加,项目进行中盲目增加人员可能造成事倍功半的效果。适用于大型项目的Rayleigh-Norden曲线[4]表明,完成软件项目的成本与时间的关系不是线性的,使用较少的人员,在可能的情况下,相对延长一些工作时间可以取得较大的经济效益。然而值得指出的是,程序员小组的正常技术交流能改进软件质量,提高软件的可维护性,减少软件错误,降低软件测试和正确性维护的开销。任务、人力、时间三者之间存在最佳组合,必须引起项目负责人的足够重视。
    2、任务分解与并行化
    软件工程项目既然需要软件开发人员集体的劳动,就需要采取一定的组织形式,将软件开发人员组织起来。软件人员的组织与分工是与软件项目的任务分解分不开的。为了缩短工程进度,充分发挥软件开发人员的潜力,软件项目的任务分解应尽力挖掘并行成分,以便软件施工时采用并行处理方式。
    3、工作量分布
    用前几节介绍的软件估算技术可以估算出软件开发各个阶段所需要的工作量,通常用人月或人年表示。软件在需求分析和设计阶段占用的工作量达到总工作量的40%~50%,说明软件开发前期的活动多么重要。当然这也包括分阶段开发原型的开销。大家熟悉的编码工作只占全部工作量的10%~20%,而软件测试和调试的工作量占到总工作量的30%~40%。这对于保证软件产品质量是十分必要的,实时嵌入式系统软件的测试和调试工作量所占的比例还要大些。
    4、工程进度安排
    软件项目的工作安排与其他工程项目的进度安排十分相似,通常的项目进度安排方法和工具稍加改造就可以用于软件项目的进度安排。目前,程序评估与审查技术(PERT)和关键路径方法(CPM)是两种比较常用的项目进度安排方法。两种方法都生成描述项目进展状态的任务网络图。网络图中按一定的次序列出所有的子任务和任务进展的里程碑,它表示各子任务之间的依赖关系。网络图也是作业分解结构(WBS)的发展。20世纪70年代,作业分解结构就已广泛应用于航天、航空、航海、雷达、通信、火控系统等领域的基于计算机项目的分解,并用以命名各项子任务,这些子任务不仅可以用网络图的形式表示,还可以用树型或层次结构图表示。PERT和CPM方法为软件规划人员提供了定量描述工具,包括:
    ①关键路径。完成关键路径上所有任务时间的总和,就是项目开发所需要的最短时间。
    ②用统计模型估算开发每个子任务需要的工作量和时间。
    ③计算各子任务的最早启动时间和最迟启动时间,即确定启动子任务的时间窗口边界。
    某个子任务的最早启动时间被定义为该子任务的所有前导任务完成的最早时间。反之,某个子任务的最迟启动时间被定义为在保证项目按时完成的前提下,最迟启动该子任务的时间。与最早启动时间和最迟启动时间对应的概念是最早结束时间和最迟结束时间。它们分别是最早启动时间和最迟启动时间与完成该子任务所需要时间的和:在任务进度安排过程中,应先寻求关键路径并在关键路径上安排一定的机动时间和节假日,以便应付意想不到的困难和问题。采用这些工具可以大大减轻软件项目管理人员在制定软件项目进度表方面的工作量,并可提高工作质量
    展开全文
  • 怎样理解线程安全

    2020-04-09 13:27:24
    目前主流操作系统任务的,即多进程同时运行。为了保证安全,每进程只能访问分配给自己的内存空间,而不能访问别的进程的,这由操作系统保障的。 在每进程的内存空间中都会有块特...

    不是线程的安全

    论语中有句话叫“学而优则仕”,相信很多人都觉得是“学习好了可以做官”。然而,这样理解却是错的。切记望文生义。

    同理,“线程安全”也不是指线程的安全,而是指内存的安全。为什么如此说呢?这和操作系统有关。

    目前主流操作系统都是多任务的,即多个进程同时运行。为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的进程的,这是由操作系统保障的。

    在每个进程的内存空间中都会有一块特殊的公共区域,通常称为堆(内存)。进程内的所有线程都可以访问到该区域,这就是造成问题的潜在原因。

    假设某个线程把数据处理到一半,觉得很累,就去休息了一会,回来准备接着处理,却发现数据已经被修改了,不是自己离开时的样子了。可能被其它线程修改了。

    比如把你住的小区看作一个进程,小区里的道路/绿化等就属于公共区域。你拿1万块钱往地上一扔,就回家睡觉去了。睡醒后你打算去把它捡回来,发现钱已经不见了。可能被别人拿走了。

    因为公共区域人来人往,你放的东西在没有看管措施时,一定是不安全的。内存中的情况亦然如此。

    所以线程安全指的是,在堆内存中的数据由于可以被任何线程访问到,在没有限制的情况下存在被意外修改的风险。

    即堆内存空间在没有保护机制的情况下,对多线程来说是不安全的地方,因为你放进去的数据,可能被别的线程“破坏”。

    那我们该怎么办呢?解决问题的过程其实就是一个取舍的过程,不同的解决方案有不同的侧重点。


    私有的东西就不该让别人知道


    现实中很多人都会把1万块钱藏着掖着,不让无关的人知道,所以根本不可能扔到大马路上。因为这钱是你的私有物品。

    在程序中也是这样的,所以操作系统会为每个线程分配属于它自己的内存空间,通常称为栈内存,其它线程无权访问。这也是由操作系统保障的。

    如果一些数据只有某个线程会使用,其它线程不能操作也不需要操作,这些数据就可以放入线程的栈内存中。较为常见的就是局部变量。
     

    double avgScore(double[] scores) {    double sum = 0;    for (double score : scores) {        sum += score;    }    int count = scores.length;    double avg = sum / count;    return avg;}

    这里的变量sum,count,avg都是局部变量,它们都会被分配在线程栈内存中。

    假如现在A线程来执行这个方法,这些变量会在A的栈内存分配。与此同时,B线程也来执行这个方法,这些变量也会在B的栈内存中分配。

    也就是说这些局部变量会在每个线程的栈内存中都分配一份。由于线程的栈内存只能自己访问,所以栈内存中的变量只属于自己,其它线程根本就不知道。

    就像每个人的家只属于自己,其他人不能进来。所以你把1万块钱放到家里,其他人是不会知道的。且一般还会放到某个房间里,而不是仍在客厅的桌子上。

    所以把自己的东西放到自己的私人地盘,是安全的,因为其他人无法知道。而且越隐私的地方越好。


    大家不要抢,人人有份


    相信聪明的你已经发现,上面的解决方案是基于“位置”的。因为你放东西的“位置”只有你自己知道(或能到达),所以东西是安全的,因此这份安全是由“位置”来保障的。

    在程序里就对应于方法的局部变量。局部变量之所以是安全的,就是因为定义它的“位置”是在方法里。这样一来安全是达到了,但是它的使用范围也就被限制在这个方法里了,其它方法想用也不用了啦。

    现实中往往会有一个变量需要多个方法都能够使用的情况,此时定义这个变量的“位置”就不能在方法里面了,而应该在方法外面。即从(方法的)局部变量变为(类的)成员变量,其实就是“位置”发生了变化。

    那么按照主流编程语言的规定,类的成员变量不能再分配在线程的栈内存中,而应该分配在公共的堆内存中。其实也就是变量在内存中的“位置”发生了变化,由一个私有区域来到了公共区域。因此潜在的安全风险也随之而来。

    那怎么保证在公共区域的东西安全呢?答案就是,大家不要抢,人人有份。设想你在街头免费发放矿泉水,来了1万人,你却只有1千瓶水,结果可想而知,一拥而上,场面失守。但如果你有10万瓶水,大家一看,水多着呢,不用着急,一个个排着队来,因为肯定会领到。

    东西多了,自然就不值钱了,从另一个角度来说,也就安全了。大街上的共享单车,现在都很安全,因为太多了,到处都是,都长得一样,所以连搞破坏的人都放弃了。因此要让一个东西安全,就疯狂的copy它吧。

    回到程序里,要让公共区域堆内存中的数据对于每个线程都是安全的,那就每个线程都拷贝它一份,每个线程只处理自己的这一份拷贝而不去影响别的线程的,这不就安全了嘛。相信你已经猜到了,我要表达的就是ThreadLocal类了。
     

    class StudentAssistant {
        ThreadLocal<String> realName = new ThreadLocal<>();    ThreadLocal<Double> totalScore = new ThreadLocal<>();
        String determineDegree() {        double score = totalScore.get();        if (score >= 90) {            return "A";        }        if (score >= 80) {            return "B";        }        if (score >= 70) {            return "C";        }        if (score >= 60) {            return "D";        }        return "E";    }
        double determineOptionalcourseScore() {        double score = totalScore.get();        if (score >= 90) {            return 10;        }        if (score >= 80) {            return 20;        }        if (score >= 70) {            return 30;        }        if (score >= 60) {            return 40;        }        return 60;    }}


    这个学生助手类有两个成员变量,realName和totalScore,都是ThreadLocal类型的。每个线程在运行时都会拷贝一份存储到自己的本地。

    A线程运行的是“张三”和“90”,那么这两个数据“张三”和“90”是存储到A线程对象(Thread类的实例对象)的成员变量里去了。假设此时B线程也在运行,是“李四”和“85”,那么“李四”和“85”这两个数据是存储到了B线程对象(Thread类的实例对象)的成员变量里去了。

    线程类(Thread)有一个成员变量,类似于Map类型的,专门用于存储ThreadLocal类型的数据。从逻辑从属关系来讲,这些ThreadLocal数据是属于Thread类的成员变量级别的。从所在“位置”的角度来讲,这些ThreadLocal数据是分配在公共区域的堆内存中的。

    说的直白一些,就是把堆内存中的一个数据复制N份,每个线程认领1份,同时规定好,每个线程只能玩自己的那份,不准影响别人的。

    需要说明的是这N份数据都还是存储在公共区域堆内存里的,经常听到的“线程本地”,是从逻辑从属关系上来讲的,这些数据和线程一一对应,仿佛成了线程自己“领地”的东西了。其实从数据所在“位置”的角度来讲,它们都位于公共的堆内存中,只不过被线程认领了而已。这一点我要特地强调一下。

    其实就像大街上的共享单车。原来只有1辆,大家抢着骑,老出问题。现在从这1辆复制出N辆,每人1辆,各骑各的,问题得解。共享单车就是数据,你就是线程。骑行期间,这辆单车从逻辑上来讲是属于你的,从所在位置上来讲还是在大街上这个公共区域的,因为你发现每个小区大门口都贴着“共享单车,禁止入门”。哈哈哈哈。

    共享单车是不是和ThreadLocal很像呀。再重申一遍,ThreadLocal就是,把一个数据复制N份,每个线程认领一份,各玩各的,互不影响。


    只能看,不能摸


    放在公共区域的东西,只是存在潜在的安全风险,并不是说一定就不安全。有些东西虽然也在公共区域放着,但也是十分安全的。比如你在大街上放一个上百吨的石头雕像,就非常安全,因为大家都弄不动它。

    再比如你去旅游时,经常发现一些珍贵的东西,会被用铁栅栏围起来,上面挂一个牌子,写着“只能看,不能摸”。当然可以国际化一点,“only look,don't touch”。这也是很安全的,因为光看几眼是不可能看坏的。

    回到程序里,这种情况就属于,只能读取,不能修改。其实就是常量或只读变量,它们对于多线程是安全的,想改也改不了。

    class StudentAssistant {
        final double passScore = 60;}

    比如把及格分数设定为60分,在前面加上一个final,这样所有线程都动不了它了。这就很安全了。

    没有规则,那就先入为主


    前面给出的三种方案,有点“理想化”了。现实中的情况其实是非常混乱嘈杂的,没有规则的。

    比如在中午高峰期你去饭店吃饭,进门后发现只剩一个空桌子了,你心想先去点餐吧,回来就坐这里吧。当你点完餐回来后,发现已经被别人捷足先登了。

    因为桌子是属于公共区域的物品,任何人都可以坐,那就只能谁先抢到谁坐。虽然你在人群中曾多看了它一眼,但它并不会记住你容颜。

    解决方法就不用我说了吧,让一个人在那儿看着座位,其它人去点餐。这样当别人再来的时候,你就可以理直气壮的说,“不好意思,这个座位,我,已经占了”。

    我再次相信聪明的你已经猜到了我要说的东西了,没错,就是(互斥)锁。

    回到程序里,如果公共区域(堆内存)的数据,要被多个线程操作时,为了确保数据的安全(或一致)性,需要在数据旁边放一把锁,要想操作数据,先获取锁再说吧。

    假设一个线程来到数据跟前一看,发现锁是空闲的,没有人持有。于是它就拿到了这把锁,然后开始操作数据,干了一会活,累了,就去休息了。

    这时,又来了一个线程,发现锁被别人持有着,按照规定,它不能操作数据,因为它无法得到这把锁。当然,它可以选择等待,或放弃,转而去干别的。

    第一个线程之所以敢大胆的去睡觉,就是因为它手里拿着锁呢,其它线程是不可能操作数据的。当它回来后继续把数据操作完,就可以把锁给释放了。锁再次回到空闲状态,其它线程就可以来抢这把锁了。还是谁先抢到锁谁操作数据。
     

    class ClassAssistant {
        double totalScore = 60;    final Lock lock = new Lock();
        void addScore(double score) {        lock.obtain();        totalScore += score;        lock.release();    }
        void subScore(double score) {        lock.obtain();        totalScore -= score;        lock.release();    }}


    假定一个班级的初始分数是60分,这个班级抽出10名学生来同时参加10个不同的答题节目,每个学生答对一次为班级加上5分,答错一次减去5分。因为10个学生一起进行,所以这一定是一个并发情形。

    因此加分和减分这两个方法被并发的调用,它们共同操作总分数。为了保证数据的一致性,需要在每次操作前先获取锁,操作完成后再释放锁。


    相信世界充满爱,即使被伤害


    再回到一开始的例子,假如你往地上仍1万块钱,是不是一定会丢呢?这要看情况了,如果是在人来人往的都市,可以说肯定会丢的。如果你跑到无人区扔地上,可以说肯定不会丢。

    可以看到,都是把东西无保护的放到公共区域里,结果却相差很大。这说明安全问题还和公共区域的环境状况有关系。

    比如我把数据放到公共区域的堆内存中,但是始终都只会有1个线程,也就是单线程模型,那这数据肯定是安全的。

    再者说,2个线程操作同一个数据和200个线程操作同一个数据,这个数据的安全概率是完全不一样的。肯定线程越多数据不安全的概率越大,线程越少数据不安全的概率越小。取个极限情况,那就是只有1个线程,那不安全概率就是0,也就是安全的。

    可能你又猜到了我想表达的内容了,没错,就是CAS。可能大家觉得既然锁可以解决问题,那就用锁得了,为啥又冒出了个CAS呢?

    那是因为锁的获取和释放是要花费一定代价的,如果在线程数目特别少的时候,可能根本就不会有别的线程来操作数据,此时你还要获取锁和释放锁,可以说是一种浪费。

    针对这种“地广人稀”的情况,专门提出了一种方法,叫CAS(Compare And Swap)。就是在并发很小的情况下,数据被意外修改的概率很低,但是又存在这种可能性,此时就用CAS。

    假如一个线程操作数据,干了一半活,累了,想要去休息。(貌似今天的线程体质都不太好)。于是它记录下当前数据的状态(就是数据的值),回家睡觉了。

    醒来后打算继续接着干活,但是又担心数据可能被修改了,于是就把睡觉前保存的数据状态拿出来和现在的数据状态比较一下,如果一样,说明自己在睡觉期间,数据没有被人动过(当然也有可能是先被改成了其它,然后又改回来了,这就是ABA问题了),那就接着继续干。如果不一样,说明数据已经被修改了,那之前做的那些操作其实都白瞎了,就干脆放弃,从头再重新开始处理一遍。

    所以CAS这种方式适用于并发量不高的情况,也就是数据被意外修改的可能性较小的情况。如果并发量很高的话,你的数据一定会被修改,每次都要放弃,然后从头再来,这样反而花费的代价更大了,还不如直接加锁呢。

    这里再解释下ABA问题,假如你睡觉前数据是5,醒来后数据还是5,并不能肯定数据没有被修改过。可能数据先被修改成8然后又改回到5,只是你不知道罢了。对于这个问题,其实也很好解决,再加一个版本号字段就行了,并规定只要修改数据,必须使版本号加1。

    这样你睡觉前数据是5版本号是0,醒来后数据是5版本号是0,表明数据没有被修改。如果数据是5版本号是2,表明数据被改动了2次,先改为其它,然后又改回到5。

    我再次相信聪明的你已经发现了,这里的CAS其实就是乐观锁,上一种方案里的获取锁和释放锁其实就是悲观锁。乐观锁持乐观态度,就是假设我的数据不会被意外修改,如果修改了,就放弃,从头再来。悲观锁持悲观态度,就是假设我的数据一定会被意外修改,那干脆直接加锁得了。

    武汉"解封"上海成最危险地方饭馆下不得?谣言!

    展开全文
  • 是怎样工作的?这样是合法的和可移植的吗? 2.8 我听说结构可以赋给变量也可以对函数传入和传出。为什么K&R1却明确说明不能这样做? 2.9 为什么不能用内建的==和!=操作符比较结构? 2.10结构传递和返回是如何...
  • 你,真的可以成为名优秀的项目组长!

    千次阅读 热门讨论 2012-07-22 16:38:59
    由于第一次,很多事情都搞不清楚,之前的几天一直在忙于UML图,也没有在怎样管理、怎样分配任务这方面多想,现在想想,就感觉自己是一个无头的苍蝇一样在偌大的房间里撞来撞去,最后弄得遍体鳞伤。  也不知
  • 从技术角度看SAP MDG是一个怎样系统?SAP MDG是一个专用的独立系统吗?SAP MDG开箱即用支持哪些主数据对象?SAP MDG支持哪些用户界面?业务用户是否可以更改工作流维护的设置?工作流是否可以按特定规则执行?是否...
  • 《你必须知道的495C语言问题》

    热门讨论 2010-03-20 16:41:18
    4.2 我想声明一个指针并为它分配一些空间,但却不行。这些代码有什么问题呢?char *p; *p =malloc(10); 45  4.3 *p++自增p还是p所指向的变量? 46 指针操作 46 4.4 我用指针操作int数组的时候遇到了麻烦。 ...
  • 4.2 我想声明一个指针并为它分配一些空间,但却不行。这些代码有什么问题呢?char *p; *p =malloc(10); 45  4.3 *p++自增p还是p所指向的变量? 46 指针操作 46 4.4 我用指针操作int数组的时候遇到了麻烦。 ...
  • 1.6 我想声明一个指针,并为它分配一些空间,但却不行。这样的代码有什么问题?char*p;*p=malloc(10);  声明风格  1.7 怎样声明和定义全局变量和函数最好? 1.8 如何在C中实现不透明(抽象)数据类型?  1.9 ...
  • 4.2 我想声明一个指针并为它分配一些空间,但却不行。这些代码有什么问题呢?char *p; *p =malloc(10); 74 4.3 *p++自增p还是p所指向的变量? 75 指针操作 75 4.4 我用指针操作int数组的时候遇到了麻烦。 75 ...
  • 1.6 我想声明一个指针,并为它分配一些空间,但却不行。这样的代码有什么问题?char*p;*p=malloc(10); 声明风格 1.7 怎样声明和定义全局变量和函数最好? 1.8 如何在C中实现不透明(抽象)数据类型? 1.9 如何...
  • 2、功能的观点 操作系统是一个计算机资源管理系统,它负责计算机系统的全部资源的分配、控制、调度和回收。 3、用户的观点 操作系统是计算机与用户之间的接口,用户通过这种接口使用计算机。 4、软件的观点 操作系统...
  • 你必须知道的495C语言问题(PDF)

    热门讨论 2009-09-15 10:25:47
    4.1 我想声明一个指针并为它分配一些空间, 但却不行。这些代码有 什么问题?char *p; *p = malloc(10); . . . . . . . . . . . . . . . . 17 4.2 *p++ 自增p 还是p 所指向的变量? . . . . . . . . . . . . . . . . ...
  • 完全免费的、源代码公开的多任务实时操作系统。它可在无任何外部数据存储器的单片80C51系统上运行,并且可移植的。全书分两部分。第部分为基础篇,介绍Small RTOS51和一些基本概念,并详细分析Small RTOS51...
  • 的机器中只有一个操作系统,当然它就是默认的操作系统,即使“Boot.ini ”文件被破坏了,也将自动地引导该系统进行装载。  解决的办法建立一个“Boot.ini”文件即可。其内容为:  [Boot Loader]  ...
  • 内核在为每一个进程分配PCB的时候,实际上是分配了两个连续的物理页面(共8K),这两个页面的底部1K空间用作进程的PCB结构,剩余7K就是这个进程的系统空间堆栈了,如图: 内核把进程的列表存放在任务队列的...
  • Hadoop家族的各个成员

    2019-07-16 19:21:07
    核心词语平台,也就是说我们有大量的数据,又有好几电脑,我们知道应该把处理数据的任务分解到各个电脑上,但是不知道怎样分配任务,怎样回收结果,hadoop大概就帮助我们做了这件事。 1、HDFS 我们首先应该...
  • 核心词语平台,也就是说我们有大量的数据,又有好几电脑,我们知道应该把处理数据的任务分解到各个电脑上,但是不知道怎样分配任务,怎样回收结果,hadoop大概就帮助我们做了这件事。 1、HDFS 我们首先应该考虑...
  • 它对于很多小任务确实很适用,但是如果处理的大型任务,它会大量消耗系统资源。由于这原因,JDK引入了StringBuffer类以提供条处理字符串的有效路径。让我们来看看怎样用这类来提升性能。  为什么不用标准...
  • 设计模式--单例模式

    2019-11-15 20:40:55
    例如,一个大公司的打印室虽然可以有多台打印机,但是其打印管理系统中只有一个打印任务控制对象,该对象管理打印排队并分配打印任务给各打印机。再如,在WIndows系统中,应该只有一个文件系统一个文件管理系统...
  • 利用线程池的优势:1、降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。2、提高响应速度。...怎样使用线程池:1、创建线程池:可以通过ThreadPoolExecutor来创建一个线程池。创...
  • 部分 ORACLE系统优化基本知识 23 第1章 ORACLE结构回顾 23 §1.1 Oracle数据库结构 23 §1.1.1 Oracle数据字典 23 §1.1.2 表空间与数据文件 24 §1.1.3 Oracle实例(Instance) 24 §1.2 Oracle文件 26 §1.2.1...
  • 是一个系统的学习Windows底层工作机制的好机会,课程内容深入浅出,精彩纷呈,绝对不容错过。 深入研究Windows内部原理系列之一:Windows的昨天、今天和明天 讲师信息:潘爱民 2007年01月25日 14:00-15:30 ...
  • 本质上是一个独立执行的程序,进程操作系统进行资源分配和调度的基本概念,操作系统进行资源分配和调度的一个独立单位。 线程: 操作系统能够进行运算调度的最小单位。它被包含在进程之中,进程中的实际...
  • java多线程笔记

    2017-12-07 21:30:25
    Day19 线程依赖于进程存在的 进程:系统调用分配资源的一种方式(如打开一个应用) 一般存在多个进程,提高CPU的使用率 ...线程依赖于进程存在的,首先需要创造一个进程,进程调用系统分配资源的,ja

空空如也

空空如也

1 2 3 4 5
收藏数 83
精华内容 33
关键字:

一个系统任务是怎样分配的