问题标签 [thread-safety]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - 实例构造函数设置一个静态成员,它是线程安全的吗?
我正在重构一些代码,并且想知道lock
在实例构造函数中使用 a 。
请确认
- 实例构造函数是线程安全的。
- lock 语句阻止访问该代码块,而不是静态“计数器”成员。
如果原始程序员的意图是让每个实例都知道它的“计数”,我将如何同步对“计数器”成员的访问,以确保另一个线程不是新线程MyClass
并在该线程设置它之前更改计数数数?
仅供参考 - 这个类不是单例。实例必须简单地知道它们的数量。
c# - 单例成员的线程安全使用
我有一个多个类使用的 C# 单例类。Instance
对方法的访问是Toggle()
线程安全的吗?如果是,根据什么假设、规则等。如果不是,为什么以及如何解决?
java - DocumentBuilder.parse() 线程安全吗?
标准的 Java 1.6 javax.xml.parsers.DocumentBuilder类线程安全吗?从多个线程并行调用 parse() 方法是否安全?
JavaDoc 没有提到这个问题,但是Java 1.4中同一个类的 JavaDoc特别指出它不是并发的;所以我可以假设在 1.6 中是这样吗?
原因是我在 ExecutorService 中运行了数百万个任务,每次调用 DocumentBuilderFactory.newDocumentBuilder() 似乎很昂贵。
java - 在 Java 中同步 String 对象
我有一个 web 应用程序,我正在对它进行一些负载/性能测试,特别是在我们预计数百名用户访问同一页面并在此页面上大约每 10 秒刷新一次的功能上。我们发现我们可以使用此功能进行的一个改进领域是将来自 Web 服务的响应缓存一段时间,因为数据没有变化。
在实现了这个基本缓存之后,在进一步的测试中我发现我没有考虑并发线程如何同时访问缓存。我发现在大约 100 毫秒的时间内,大约 50 个线程试图从缓存中获取对象,发现它已经过期,访问 Web 服务以获取数据,然后将对象放回缓存中。
原始代码看起来像这样:
因此,为了确保在对象key
过期时只有一个线程在调用 Web 服务,我认为我需要同步 Cache get/set 操作,并且似乎使用缓存键将是对象的一个很好的候选者同步(这样,对电子邮件 b@b.com 的此方法的调用不会被对 a@a.com 的方法调用阻止)。
我将方法更新为如下所示:
我还为“同步块之前”、“同步块内部”、“即将离开同步块”和“同步块之后”等内容添加了日志记录行,这样我就可以确定我是否有效地同步了 get/set 操作。
然而,这似乎没有奏效。我的测试日志的输出如下:
我希望一次只看到一个线程进入/退出围绕 get/set 操作的同步块。
在 String 对象上同步是否存在问题?我认为缓存键是一个不错的选择,因为它是操作所独有的,即使final String key
在方法中声明了,我认为每个线程都会获得对同一个对象的引用,因此会对此进行同步单个对象。
我在这里做错了什么?
更新:进一步查看日志后,似乎具有相同同步逻辑的方法,其中密钥始终相同,例如
不要表现出相同的并发问题 - 一次只有一个线程进入块。
更新2:感谢大家的帮助!我接受了关于intern()
ing Strings 的第一个答案,这解决了我最初的问题 - 多个线程正在进入我认为它们不应该进入的同步块,因为key
' 具有相同的值。
正如其他人所指出的那样,intern()
出于这样的目的并在这些字符串上同步确实是一个坏主意 - 当对 webapp 运行 JMeter 测试以模拟预期负载时,我看到使用的堆大小增长到近 1GB不到20分钟。
目前我正在使用仅同步整个方法的简单解决方案 - 但我真的很喜欢 martinprobst 和 MBCook 提供的代码示例,但是因为我getData()
目前在这个类中有大约 7 个类似的方法(因为它需要大约 7 个不同的数据来自 Web 服务),我不想为每个方法添加关于获取和释放锁的几乎重复的逻辑。但这对于未来的使用绝对是非常非常有价值的信息。我认为这些最终是关于如何最好地使这种线程安全的操作的正确答案,如果可以的话,我会给这些答案更多的投票!
.net - 有没有人写过一个线程安全的 BindingList?
我目前在多个线程上修改 IBindingList 时遇到异常。在我自己编写之前,有人有线程安全版本吗?
c# - 实现线程安全字典的最佳方法是什么?
通过从 IDictionary 派生并定义私有 SyncRoot 对象,我能够在 C# 中实现线程安全字典:
然后我在整个消费者(多个线程)中锁定这个 SyncRoot 对象:
例子:
我能够让它工作,但这导致了一些丑陋的代码。我的问题是,是否有更好、更优雅的方式来实现线程安全字典?
c# - 类设计:根据线程安全性和可测试性将数据文件包装成一个类
我正在用 C# (.net 3.5) 编写一个应用程序,我有一个关于类设计的问题:
我想创建一个访问文件(读、写)并将其内容提供给该类的用户(实例化器)的类。实例上最常见的操作是从文件中检索某个值。实际的读写(io)操作非常昂贵,所以我想将文件数据保存在内存中并让所有实例访问这些数据。该类位于同时从各种应用程序中使用的程序集中,所以我想我应该担心线程安全。
关于线程安全和单元可测试性,我该如何设计(对于单元测试,必须使用与操作代码不同的输入文件)?任何帮助是极大的赞赏。
java - 我应该始终使我的 java 代码线程安全,还是出于性能原因仅在需要时才这样做?
如果我创建目前仅在单个线程中使用的类,我是否应该使它们成为线程安全的,即使我目前不需要它?可能会发生,我后来在多个线程中使用这个类,那时我可能会遇到竞争条件,如果我没有首先使类线程安全,可能很难找到它们。或者我应该让这个类不是线程安全的,以获得更好的性能?但是过早的优化是邪恶的。
不同的问题:如果需要,我应该使我的类线程安全(如果在多个线程中使用,否则不是)还是应该优化这个问题然后需要(如果我看到同步占用了处理时间的重要部分)?
如果我选择两种方式中的一种,是否有减少缺点的方法?还是存在我应该使用的第三种可能性?
编辑:我给出了我想到这个问题的原因。在我们公司,我们编写了一个非常简单的用户管理,将数据写入属性文件。我在一个网络应用程序中使用它,经过一些工作后我得到了奇怪的错误,用户管理忘记了用户的属性(包括名称和密码)和角色。这很烦人,但不能始终如一地重现,所以我认为这是竞争条件。由于我同步了从磁盘读取和写入的所有方法,因此问题消失了。所以我想,如果我们一开始就编写了带同步的类,我可能可以避免所有的麻烦?
编辑 2:当我查看实用程序员的技巧时,我看到了技巧 #41:始终为并发设计。这并不是说所有代码都应该是线程安全的,而是说设计应该考虑到并发性。
c++ - 这个用于原子浮点的 C++ 实现安全吗?
编辑:这里的代码仍然有一些错误,它可以在性能部门做得更好,但是我没有尝试修复这个问题,而是将问题提交给英特尔讨论组并得到了很多很好的反馈,如果一切顺利,Atomic float 的抛光版本将包含在英特尔线程构建模块的近期版本中
好的,这是一个艰难的,我想要一个原子浮点数,不是为了超快的图形性能,而是作为类的数据成员常规使用。而且我不想为在这些类上使用锁付出代价,因为它没有为我的需求提供额外的好处。
现在有了英特尔的 tbb 和我见过的其他原子库,支持整数类型,但不支持浮点。所以我继续实施了一个,它有效......但我不确定它是否真的有效,或者我很幸运它有效。
这里的任何人都知道这是否不是某种形式的线程异端?
谢谢!
编辑:按照 Greg Rogers 的建议将 size_t 更改为 uint32_t,这样它更便携
编辑:为整个事物添加了列表,并进行了一些修复。
更多编辑:在我的机器上使用锁定浮点数进行 5.000.000 += 操作(在我的机器上使用 100 个线程)需要 3.6 秒,而我的原子浮点数即使是愚蠢的 do-while 也需要 0.2 秒才能完成相同的工作。因此,> 30 倍的性能提升意味着它是值得的,(这就是问题所在)如果它是正确的。
更多编辑:正如 Awgn 指出的那样,我的fetch_and_xxxx
部分都错了。修复了这个问题并删除了我不确定的部分 API(模板化内存模型)。并在运算符 += 方面实现了其他操作,以避免代码重复
添加:添加了运算符 *= 和运算符 /=,因为没有它们,浮点数就不会是浮点数。感谢 Peterchen 的评论,这被注意到了
编辑:最新版本的代码如下(我将保留旧版本以供参考)
c++ - Matlab引擎API的线程安全
我通过反复试验发现 MATLAB 引擎函数不是完全线程安全的。
有人知道规则吗?
通过反复试验发现:
在 Windows 上,与 MATLAB 的连接是通过 COM 进行的,因此适用 COM Apartment 线程规则。所有调用都必须发生在同一个线程中,但是多个连接可以发生在多个线程中,只要每个连接都是隔离的。
从下面的答案来看,在 UNIX 上似乎不是这种情况,只要调用是串行进行的,就可以从多个线程进行调用。