天道酬勤,学无止境

Race conditions when adding to, but not reading from, a List<T> (or Stack or Queue) - what happens?

Note: I'm asking this question relative to the 3.5 framework, so I'm not including any of the newer multithreaded constructs in 4.0 (which I'm still learning).

I've been trying to come up with an answer on this to try and close out an argument I've been having, but I don't feel like I've found a conclusive description as to what would or could happen in the following scenario.

Say you have an app with multiple threads that are all generating objects, with each thread generating a unique object. There's a single instance of a collection (List, Stack, or Queue) that's the repository for the objects once they've been created, and the objects are effectively immutable once added to the collection.

During this process, the only operation on the collection is adding items. There's no reading, removing, or counting done. It doesn't matter what the order of the items are in the collection.

The question is, if there is no locking around the collection when the individual threads are trying to add objects, is that really a problem?

I say yes, but pretty much all of the textbook descriptions of why race conditions are problematic have a read on one end and a race on the other or are writing to a single variable, so I don't have enough evidence to argue my case effectively.

My reason for saying yes is basically down to the fact that the collections are not designed to be thread safe, so you could wind up with unexpected or undefined behavior, even if only "writes" are being performed. I'd guess that there is a risk that two threads might try adding their object to the same slot in the collection, and therefore you'd loose an object when it gets overwritten, but I haven't found anything that says that it is indeed possible. Or that there might be some behind-the-scenes problems, such as when the collection needs to grow itself to accommodate more items.

Can someone provide me with some information to help put this argument to rest? I'm especially interested to hear if there's anything that would prove me wrong.

评论

Adding items to a List<T> (or stack, etc) is not thread-safe.

This involves

  • Checking if internal array size is sufficient
  • If not, create a new array, copy all items
  • Set item in the array with the index equal to the length of the List<T>

None of the above processes are thread safe and there are no synchronisation in .NET framework code. So if you do not synchronise, I guarantee your list will be corrupted.

Adding items to a list involves reading and writing of memory so unless there is synchronization there is a race.

You're basically right, although some of the simpler structures like a stack or queue might be "accidentally" thread safe. You have no guarantee on how the "internals" of any collection are implemented. For example, a list is backed by an array. If you add a new item that causes it to grow the array, it will (could) copy all of the values to a new larger array. This is probably thread safe in its implementation, but since it's not a threadsafe object, there's no contract to its thread safety.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 使用 Redux 获取数据时如何避免竞争条件?(How to avoid race conditions when fetching data with Redux?)
    问题 我们有一个异步获取对象的操作,我们称之为getPostDetails ,它通过 id 获取要获取哪个帖子的参数。 用户会看到一个帖子列表,可以点击一个来获取一些详细信息。 如果用户点击“Post #1”,我们会发送一个GET_POST动作,它可能看起来像这样。 const getPostDetails = (id) => ({ type: c.GET_POST_DETAILS, promise: (http) => http.get(`http://example.com/posts/#${id}`), returnKey: 'facebookData' }) 这是由中间件获取的,它向承诺添加一个成功处理程序, GET_POST__OK使用反序列化的 JSON 对象调用诸如GET_POST__OK之类的操作。 减速器看到这个对象并将它应用到商店。 一个典型的__OK减速器看起来像这样。 [c.GET_ALL__OK]: (state, response) => assign(state, { currentPost: response.postDetails }) 稍后,我们有一个组件可以查看currentPost并显示当前帖子的详细信息。 但是,我们有一个竞争条件。 如果用户一个接一个地提交两个GET_POST_DETAILS动作,则无法保证我们收到__OK动作的顺序
  • 在多个 chrome.storage API 调用中防止竞争条件的最佳方法?(Best way to prevent race condition in multiple chrome.storage API calls?)
    问题 某事请求任务其他东西从存储中提取任务列表,并检查那里是否有任务。 如果有任务,它会删除一个,并将较小的“任务列表”放回存储中。 在第 2 步和第 3 步之间,如果发生多个请求,可能会出现竞争条件,并且同一任务将被提供两次。 在“签出”单个任务时“锁定”“任务表”以防止任何其他请求的正确解决方案是否正确? 对性能影响最小的解决方案是什么,例如执行延迟,应该如何在带有 chrome.storage API 的 javascript 中实现? 一些代码例如: function decide_response ( ) { if(script.replay_type == "reissue") { function next_task( tasks ) { var no_tasks = (tasks.length == 0); if( no_tasks ) { target_complete_responses.close_requester(); } else { var next_task = tasks.pop(); function notify_execute () { target_complete_responses.notify_requester_execute( next_task ); } setTable("tasks", tasks, notify
  • 牛客 剑指offer_编程题 详细题解 (已完结)
    文章目录 剑指offer_编程题【1.二维数组中的查找】【2.替换空格】C++Java 【3.从尾到头打印链表】【4.重建二叉树】【5.用两个栈实现队列】【6.旋转数组的最小数字】暴力Sort二分法 【7.斐波那契数列】【8.跳台阶】【9.变态跳台阶】【10.矩形覆盖】【11.二进制中1的个数】暴力>>>规律 【12.数值的整数次方】【13.调整数组顺序使其位于偶数前面】创建临时数组借鉴插入排序 【14.链表倒数第k个节点】【15.反转链表】【16.合并两个有序链表】【17.树的子结构】【17.二叉树的镜像】【18.顺时针打印矩阵】【19.包含min的栈】【20.栈的压入、弹出序列】【21.从上向下打印二叉树】【22.二叉搜索树的后序遍历序列】【23.二叉树中和为某一值的路径】【24.复杂链表的复制】【25.二叉搜索树与双向链表】【26.字符串的排列】【27.数组中出现次数超过一半的数字】【28.最小的k个数】【29.连续数组的最大和】【30.整数中1出现的次数】【31.把数组排成最小的数】【32.丑数】【33.第一个只出现一次的字符】【34.数组中的逆序对】【35.两个链表的第一个公共节点】递归非递归 【36.数字在排序数组中出现的次数】【37.二叉树的深度】【38.平衡二叉树】【39.数组中只出现一次的数字】【40.和为S的连续正整数序列】【41.和为S的两个数字】【42
  • updateSelectInput 操作顺序/竞争条件(updateSelectInput order of operations/race condition)
    问题 我正在使用目录中的文件名填充带有 updateSelectInput 的 selectInput。 用户使用 radioButtons 输入选择要填充的目录。 一切正常,但是当应用程序首次加载或目录更改时, selectInput 反应传递默认值或旧目录中最后选择的文件(分别用于启动和目录更改)。 这会导致数据文件加载失败,直到 selectInput 更新。 如何让我的文件加载反应性等待 selectInput 更新? 这是相关的代码... 用户界面: radioButtons("system", label = h3("System"), choices = list("USAMS" = usamspath, "CFAMS" = cfamspath), selected = usamspath), selectInput("wheelSelect", label = h3("Wheel"), c("label 1" = "option1")), 服务器.R: observe({ #Get and order wheelnames details <- file.info(list.files(path = input$system, pattern = "*AMS*.*", full.names=TRUE)) details <- details[with(details
  • 单线程程序中可以有竞争条件吗?(Can we have race conditions in a single-thread program?)
    问题 您可以在这里找到关于什么是竞赛条件的很好的解释。 最近,我看到许多人对竞争条件和线程发表了令人困惑的声明。 我了解到,竞争条件只能在线程之间发生。 但是我看到了在事件和基于异步的语言中看起来像竞争条件的代码,即使该程序是单线程的,例如在Node.js,GTK +等中也是如此。 我们可以在单线程程序中有一个竞争条件吗? 回答1 所有示例均使用非常接近Javascript的虚构语言编写。 短的: 争用条件只能发生在两个或多个线程/外部状态之间(其中一个可以是OS)。 我们不能在非I / O执行程序的单线程进程中具有竞争条件。 但是在许多情况下,单线程程序可以: 给出与竞赛条件类似的情况,例如在带有事件循环的基于事件的程序中,但不是真实的竞赛条件例如,或由于程序某些部分的执行取决于外部状态,而触发在其他线程之间或与其他线程之间的竞争条件: 其他程序,例如客户端库线程或服务器系统时钟 I)竞争条件只能在两个或多个线程之间发生 仅当两个或多个线程尝试访问共享资源而又不知道其他线程的未知指令同时修改了共享资源时,才会发生竞争状态。 这给出了不确定的结果。 (这真的很重要。) 即使不容易在代码中读取指令的执行顺序,单线程处理也不过是一系列已知指令的结果,因此可以得出确定的结果。 II)但是我们并不安全 II.1)类似于比赛条件的情况 许多编程语言通过事件或信号实现异步编程功能
  • 竞争条件“check-then-act”和“read-modify-write”(Race conditions “check-then-act” and “read-modify-write”)
    问题 任何人都可以向我解释什么是竞争条件,如何避免它,以及如何在 Java 代码中找到它? 好吧,我几天才知道“竞争条件”,我有两个例子,也许它们不够好,这就是为什么我需要你的帮助:)希望你们中的任何人都可以为我解释。 示例1:检查然后采取行动: if(vector.contains(e))//check { vector.remove(e) } 如果有2个线程可以访问,线程1在检查向量包含e后挂起,e在向量中,然后线程2访问检查然后从向量中删除e,然后线程1回来做删除动作,会发生错误,因为e是已被 thread2 删除。 示例2:读取修改写入: 假设我们在一个方法中有一个计数器变量,一旦方法被调用,计数器增加1, counter++ 这不是原子操作,它有 3 个步骤: 1. 获取值 2. 增加值 3. 分配给值 我对比赛条件的了解都在这里,希望您能与我分享您的知识:) 谢谢 回答1 什么是竞态条件? 检查这个堆栈溢出问题。 竞争条件主要有两种情况:读-修改-写和检查-然后-行动。 对于读取-修改-写入,经典示例是counter++ ,它不是原子操作,因此会导致竞争条件。 对于先检查后行动,有多个示例。 一个例子是当你在 ConcurrentHashMap 中检查键是否存在,然后在 if-case 中做一些工作。 另一个例子是单例类代码: public Singleton
  • Django中的原子操作?(Atomic operations in Django?)
    问题 我正在尝试为计数器实现(我认为是)一个非常简单的数据模型: class VisitorDayTypeCounter(models.Model): visitType = models.CharField(max_length=60) visitDate = models.DateField('Visit Date') counter = models.IntegerField() 当有人通过时,它将寻找与visitType和visitDate匹配的行; 如果该行不存在,则将使用counter = 0创建它。 然后我们增加计数器并保存。 我担心的是,这个过程完全是一场比赛。 两个请求可以同时检查该实体是否存在,并且两个都可以创建它。 在读取计数器和保存结果之间,可能会通过另一个请求并将其递增(导致计数丢失)。 到目前为止,无论是在Django文档中还是在教程中,我还没有真正找到解决此问题的好方法(实际上,该教程在其Vote部分中似乎具有竞争条件)。 我该如何安全地执行此操作? 回答1 这有点骇人听闻。 原始SQL将使您的代码可移植性降低,但是它将摆脱计数器增量上的竞争条件。 从理论上讲,这将在您每次查询时增加计数器的数量。 我尚未对此进行测试,因此您应确保在查询中正确插入列表。 class VisitorDayTypeCounterManager(models.Manager)
  • 什么情况下System.Collections.ArrayList.Add抛出IndexOutOfRangeException?(Under what circumstance System.Collections.ArrayList.Add throws IndexOutOfRangeException?)
    问题 我们在生产环境中遇到奇怪的错误,无法调试或注入日志记录代码。 我试图弄清楚这一点,但是下面的堆栈跟踪使我感到困惑。 System.IndexOutOfRangeException: Index was outside the bounds of the array. at System.Collections.ArrayList.Add(Object value) at ... 根据MSDN, Add方法应仅抛出NotSupportedException 。 我不知道这是怎么回事。 你? 回答1 归结为List不是线程安全的。 使用多个线程在没有同步的情况下添加项目之后,在遍历列表时发生IndexOutOfRangeException。 以下代码可能会破坏项目计数,并在随后迭代列表时导致IndexOutOfRangeException, List<TradeFillInfo> updatedFills = new List<TradeFillInfo>(); Parallel.ForEach (trades, (trade) => { TradeFillInfo fill = new TradeFillInfo(); //do something updatedFills.Add(fill); //NOTE:Adding items without
  • 超详细动画彻底掌握深度优先,广度优先遍历!
    前言深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath First Search)是图论中两种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷宫),搜索引擎,爬虫等,也频繁出现在 leetcode,高频面试题中。本文将会从以下几个方面来讲述深度优先遍历,广度优先遍历,想信大家看了肯定会有收获。深度优先遍历,广度优先遍历简介习题演练DFS,BFS 在搜索引擎中的应用深度优先遍历,广度优先遍历简介深度优先遍历深度优先遍历主要思路是从图中一个未访问的顶点 V 开始,沿着一条路一直走到底,然后从这条路尽头的节点回退到上一个节点,再从另一条路开始走到底…,不断递归重复此过程,直到所有的顶点都遍历完成,它的特点是不撞南墙不回头,先走完一条路,再换一条路继续走。树是图的一种特例(连通无环的图就是树),接下来我们来看看树用深度优先遍历该怎么遍历。1、我们从根节点 1 开始遍历,它相邻的节点有 2,3,4,先遍历节点 2,再遍历 2 的子节点 5,然后再遍历 5 的子节点 9。2、上图中一条路已经走到底了(9是叶子节点,再无可遍历的节点),此时就从 9 回退到上一个节点 5,看下节点 5 是否还有除 9 以外的节点,没有继续回退到 2,2 也没有除 5 以外的节点,回退到 1,1 有除 2 以外的节点 3,所以从节点 3 开始进行深度优先遍历,如下3
  • ConcurrentHashMap 上的竞争条件问题(Problems with race conditions on ConcurrentHashMap)
    问题 我有一个多线程应用程序,其中 n 个线程写入ConcurrentHashMap 。 另一个 n 线程从该 Map 中读取并将其值复制到副本列表中。 之后,原始列表从地图中删除。 出于某种原因,我总是收到ConcurrentModificationException 。 我什至尝试使用可变布尔值创建自己的锁定机制,但它不起作用。 将Google Guava与Lists.newLinkedList()我收到ConcurrentModificationException 。 当使用 StandardWay new LinkedList(list)我得到一个ArrayOutOfBoundsException 。 下面是编译代码示例: public class VolatileTest { public static Map<String, List<String>> logMessages = new ConcurrentHashMap<String, List<String>>(); public static AtomicBoolean lock = new AtomicBoolean(false); public static void main(String[] args) { new Thread() { public void run() { while (true) {
  • 用李克特软件包绘制百分比-分组时不起作用(Plot Percents with Likert Package - Doesn`t work when grouping)
    问题 我已经使用Likert包创建了一些图表,但是当我按组创建图表时,plot.percents = TRUE不会为我提供每个响应类别的标签。 plot.percents.high = TRUE和plot.percents.low = TRUE为我提供了组合百分比,但是我希望所有响应类别都使用该百分比。 它可以很好地与未分组的数据一起使用。 我使用的代码是: 做一些数据 library(likert) library (reshape) Group <- c("Group 1", "Group 1", "Group 1", "Group 1", "Group 1", "Group 1", "Group 1", "Group 2", "Group 2", "Group 2", "Group 2", "Group 2", "Group 2","Group 2", "Group 3", "Group 3", "Group 3", "Group 3","Group 3","Group 3","Group 3") Var1 <- c("Agree", "Agree", "Strongly agree", "Agree", "Strongly disagree", "Agree","Strongly agree", "Disagree", "Strongly agree", "Strongly
  • 哈希表或哈希表中的重新哈希处理(Rehashing process in hashmap or hashtable)
    问题 当大小超过maxthreshold值时,如何在哈希图或哈希表中进行重新哈希处理? 是否所有对都已复制到新的存储桶阵列中? 编辑: 重新哈希后,同一存储桶(位于链接列表中)中的元素会发生什么情况? 我的意思是说,他们在重新哈希处理后会留在同一个桶中吗? 回答1 问题中的最大阈值称为负载系数。 建议负载系数约为0.75。 负载因子定义为(m / n),其中n是哈希表的总大小,m是在需要增加基础数据结构的大小之前可以插入的首选条目数。 可以在两种情况下进行重新哈希处理: 当当前的m'/ n比值超出负载系数时 M'/ n比降到非常低的值,例如0.1 在两种情况下,m'是当前条目数。 同样,这两种情况都要求将当前条目移动到更大或更小的哈希表中。 在问题的上下文中,重新哈希处理是将哈希函数应用于条目以将其移动到另一个哈希表的过程。 可以使用以前使用的哈希函数或完全使用新函数。 请注意:当发生冲突时,也会进行重新哈希处理。 (这也是处理冲突的一种方法。) 要添加更多上下文和详细讨论,请访问我的博客Hashing Basics 回答2 当哈希图中的元素数量达到最大阈值时,将对哈希图进行重新哈希处理。 通常,负载系数值为0.75,默认初始容量值为16。一旦元素数量达到或超过容量的0.75倍,就会重新映射。 在这种情况下,当元素数为12时,将发生重新哈希。 (0.75 * 16 = 12)
  • node.js代码会导致竞态条件吗?(Can node.js code result in race conditions?)
    问题 据我所知,当不同的线程试图更改一个共享变量时,就会出现竞争条件,这可能导致这些线程的任何串行执行顺序都无法获得该值。 但是node.js中的代码在单个线程中运行,那么,这是否意味着用node.js编写的代码没有竞争条件? 回答1 是的。 一旦开始共享资源,Node.js可能会陷入竞争状态。 我也错误地认为您无法在Node.js中获得竞争条件,因为它是单线程性质,但是一旦您在节点外部使用共享资源(例如,文件系统中的文件),您就可以进入竞争条件。 当我尝试理解此问题时,我在此问题中发布了此问题的示例:node.js readfile出现问题 Node.js与其他环境的不同之处在于,您只有一个JavaScript执行线程,因此只有一个JavaScript实例在运行您的代码(与线程环境相反,在该线程环境中,有许多线程在同一时间执行您的应用程序代码时间。) 回答2 是的,竞争条件(在某种意义上说,共享资源由于事件顺序而导致的值不一致)仍然可能发生在任何可能导致其他代码运行的暂停点(线程在任何行上)的任何地方。例如,这段异步代码完全是单线程的: var accountBalance = 0; async function getAccountBalance() { // Suppose this was asynchronously from a database or
  • 加载实体时休眠竞争条件(nhibernate race condition when loading entity)
    问题 我的 webapp 中的 nhibernate 竞争条件有问题。 我知道在使用旧版本的 log4net 时会发生这种情况(应该在 1.2.10 中修复),尽管我也遇到过这种情况。 因此,我们暂时禁用了 log4net,因为竞争条件会导致 IIS 崩溃,并且在生产中发生这种情况是不可接受的。 这发生在加载实体时(参见下面的堆栈跟踪)。 除此之外,RavenDB 中似乎也发生了类似的问题,请参阅此链接,以及此处链接的没有 NHibernate 的示例。 堆栈跟踪: Server Error in '/' Application. Probable I/O race condition detected while copying memory. The I/O package is not thread safe by default. In multithreaded applications, a stream must be accessed in a thread-safe way, such as a thread-safe wrapper returned by TextReader's or TextWriter's Synchronized methods. This also applies to classes like StreamWriter and
  • 空合并运算符线程安全吗?(Is the null coalesce operator thread safe?)
    问题 所以这就是问题的核心:Foo.Bar 是否可以返回 null? 澄清一下,是否可以将 '_bar' 在评估为非空值之后和返回值之前将其设置为空值? public class Foo { Object _bar; public Object Bar { get { return _bar ?? new Object(); } set { _bar = value; } } } 我知道使用以下 get 方法不安全,并且可以返回空值: get { return _bar != null ? _bar : new Object(); } 更新: 另一种看待同一问题的方式,这个例子可能更清楚: public static T GetValue<T>(ref T value) where T : class, new() { return value ?? new T(); } 再次询问 GetValue(...) 是否可以返回 null? 根据您的定义,这可能是也可能不是线程安全的......我想正确的问题陈述是询问它是否是对值的原子操作...... David Yaw 最好地定义了这个问题,他说上面的函数是等价的到以下几点: public static T GetValue<T>(ref T value) where T : class, new() { T result =
  • SQL Server竞争条件问题(SQL Server Race Condition Question)
    问题 (注意:这是针对MS SQL Server的) 假设您有一个具有主键标识列和CODE列的表ABC。 我们希望此处的每一行都有一个唯一的,顺序生成的代码(基于一些典型的校验位公式)。 假设您有另一个仅具有一行的表DEF,该表存储下一个可用的CODE(想象一个简单的自动编号)。 我知道像下面这样的逻辑将呈现一种竞争状态,其中两个用户可能最终得到相同的CODE: 1) Run a select query to grab next available code from DEF 2) Insert said code into table ABC 3) Increment the value in DEF so it's not re-used. 我知道,两个用户可能会卡在步骤1)中,并最终在ABC表中得到相同的CODE。 处理这种情况的最佳方法是什么? 我以为可以围绕此逻辑包装“ begin tran” /“ commit tran”,但我认为那没有用。 我有一个像这样的存储过程来测试,但是当我从MS中的两个不同窗口运行时,我并没有避免竞争条件: begin tran declare @x int select @x= nextcode FROM def waitfor delay '00:00:15' update def set nextcode = nextcode + 1
  • .NET:EventHandler 竞争条件修复如何工作?(.NET: How does the EventHandler race-condition fix work?)
    问题 有以下模式用于在引发事件时避免竞争条件,以防另一个线程取消订阅 MyEvent,使其为空。 class MyClass { public event EventHandler MyEvent; public void F() { EventHandler handler = MyEvent; if(handler != null) handler(this, EventArgs.Empty); } } 与容易出现这种竞争条件的错误做法相反: class MyClass { public event EventHandler MyEvent; public void F() { if(MyEvent != null) MyEvent(this, EventArgs.Empty); } } 我的问题是,鉴于System.Delegate是一个引用类型:如果 MyEvent 不为空,怎么会 EventHandler handler = MyEvent; 似乎复制其调用列表而不是获取引用。 我希望将 MyEvent 委托分配给“处理程序”变量,然后一旦有人更改了MyEvent,“处理程序”引用的对象也将更改。 显然,事实并非如此,否则这个漂亮的小图案将不起作用。 我查看了 .NET 源代码,但仍然无法在那里找到我的答案(它可能在那里,但我已经找了大约一个小时但找不到它,所以我在这里。
  • 二叉树:你真的会翻转二叉树么?
    226.翻转二叉树 翻转一棵二叉树。 这道题目背后有一个让程序员心酸的故事,听说 Homebrew的作者Max Howell,就是因为没在白板上写出翻转二叉树,最后被Google拒绝了。(真假不做判断,权当一个乐子哈) 题外话 这道题目是非常经典的题目,也是比较简单的题目(至少一看就会)。 但正是因为这道题太简单,一看就会,一些同学都没有抓住其本质,稀里糊涂的就把这道题目过了。 如果做过这道题的同学也建议认真看完,相信一定有所收获! 思路 我们之前介绍的都是各种方式遍历二叉树,这次要翻转了,感觉还是有点懵逼。 这得怎么翻转呢? 如果要从整个树来看,翻转还真的挺复杂,整个树以中间线进行翻转,如图: 可以发现想要翻转它,其实就把每一个节点的左右孩子交换一下(注意孩子下面的节点是一起交换的)就可以了。 关键在于遍历顺序,前中后序应该选哪一种遍历顺序?(一些同学这道题都过了,但是不知道自己用的是什么顺序) 遍历的过程中去翻转每一个节点的左右孩子就可以达到整体翻转的效果。 「注意只要把每一个节点的左右孩子翻转一下,就可以达到整体翻转的效果」 「这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不行,因为中序遍历会把某些节点的左右孩子翻转了两次!建议拿纸画一画,就理解了」 那么层序遍历可以不可以呢?「依然可以的!只要把每一个节点的左右孩子翻转一下的遍历方式都是可以的!」 递归法
  • C++ STL的容器(map、vector、list、set)
    下面许多代码都省略了#include <map> #include <string> map(#include <map>) map是STL的一个关联容器,它提供一对一(关键字+关键字的值)的数据处理能力。 下面给出map描述代码: map的构造函数 map共提供了6个构造函数,我们通常用如下方法构造一个map: Map<int, string> mapStudent; 数据的插入 三种插入数据的方法:下列三种方法输出都为 1 student_one 2 student_two 3 student_three 第一种:用insert函数插入pair数据 int main(){ map<int, string> mapStudent; mapStudent.insert(pair<int, string>(1, "student_one")); mapStudent.insert(pair<int, string>(2, "student_two")); mapStudent.insert(pair<int, string>(3, "student_three")); map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++){ cout<<iter
  • 竞态条件和死锁之间的区别(Difference between racearound condition and deadlock)
    问题 用编程术语来说,死锁和争用条件有什么区别? 回答1 使用传统示例来考虑竞争条件。 假设您和朋友使用同一个银行帐户的ATM卡。 现在假设帐户中有$ 100。 请考虑一下,当您尝试提取10美元而您的朋友尝试同时完全提取50美元时会发生什么。 考虑发生什么情况。 ATM机必须接受您的输入,读取您帐户中当前的内容,然后修改金额。 请注意,就编程而言,赋值语句是一个多步骤过程。 因此,标记您的两个交易T1(您提取10美元)和T2(您的朋友提取50美元)。 现在,下面左侧的数字代表时间步长。 T1 T2 ---------------- ------------------------ 1. Read Acct ($100) 2. Read Acct ($100) 3. Write New Amt ($90) 4. Write New Amt ($50) 5. End 6. End 两次交易完成后,使用此时间表(如果您不使用任何形式的锁定机制,则该帐户中就有50美元)是可行的。 这比应有的金额高出10美元(您的交易会永远丢失,但您仍然有钱)。 这就是所谓的竞赛条件。 您想要的是使事务可序列化,即无论您如何交错执行各个指令,最终结果都将与某些串行调度完全相同(这意味着您不进行交错就一次接一个地运行它们)相同的交易。 同样,解决方案是引入锁定。 但是,错误的锁定会导致死锁。 共享资源冲突时