我有一个带有两个线程的简单场景,其中第一个线程永久读取一些数据并将该数据排入队列.第二个线程首先从该队列中查看单个对象并进行一些条件检查.如果这些是好的,单个对象将被出列并传递给某些处理.
我试图使用ConcurrentQueue这是一个简单队列的线程安全实现,但这个问题是所有调用都是阻塞.这意味着如果第一个线程将对象排入队列,则第二个线程无法查看或出列对象.
在我的情况下,我需要在最后排队并同时从队列的开头出队.
C#的锁定语句也会.
所以我的问题是,是否可以并行执行这两个操作而不会以线程安全的方式相互阻塞.
这些是我的第一次尝试,这是我的问题的类似示例.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Scenario {
public class Program {
public static void Main(string[] args) {
Scenario scenario = new Scenario();
scenario.Start();
Console.ReadKey();
}
public class Scenario {
public Scenario() {
someData = new Queue<int>();
}
public void Start() {
Task.Factory.StartNew(firstThread);
Task.Factory.StartNew(secondThread);
}
private void firstThread() {
Random random = new Random();
while (true) {
int newData = random.Next(1, 100);
someData.Enqueue(newData);
Console.WriteLine("Enqueued " + newData);
}
}
private void …Run Code Online (Sandbox Code Playgroud) 我使用此方法初始化具有默认值的ArrayList:
private ArrayList<Integer> createArrayList(int size, int defaultValue)
{
ArrayList<Integer> arrayList = new ArrayList<>(size);
IntStream.range(0, size ).parallel().forEach(i->{arrayList.add(defaultValue);});
return arrayList;
}
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,如果我通过单元测试检查返回数组的大小,它不是固定数字,并且几乎总是小于请求的大小.
如果我删除parallel()它的大小总是按要求.
为什么会这样?
我正在尝试建立一个模型,在该模型中,我将多次读取整个集合,并对其进行罕见的添加和修改。
我以为我ConcurrentBag在阅读文档时可能会在.NET中使用它,因此对于并发读写来说应该是不错的选择。
代码如下所示:
public class Cache
{
ConcurrentBag<string> cache = new ConcurrentBag<string>();
// this method gets called frequently
public IEnumerable<string> GetAllEntries()
{
return cache.ToList();
}
// this method gets rarely called
public void Add(string newEntry)
{
// add to concurrentBag
}
public void Remove(string entryToRemove)
{
// remove from concurrent bag
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我已经对该ConcurrentBag类进行了反编译,并且GetEnumerator始终会进行锁定,这意味着对GetAllEntries的任何调用都会锁定整个集合,并且将无法执行。
我正在考虑解决此问题,并使用列表以这种方式进行编码。
public class Cache
{
private object guard = new object();
IList<string> cache = new List<string>();
// this method gets …Run Code Online (Sandbox Code Playgroud) 我正在寻找可能对此有更多了解的人,我的直觉告诉我答案是“不,它不是线程安全的”,但我想确定。
为了说明我的问题,我为此类提供了一些背景信息
public class MyContext
{
private readonly object _lock = new object();
public delegate bool MyDelegate(MyContext context);
private MyDelegate _multicastDelegate;
public MyContext()
{
_multicastDelegate = null;
}
public void AddDelegate(MyDelegate del)
{
lock(_lock)
{
_multicastDelegate += del;
}
}
public void RemoveDelegate(MyDelegate del)
{
lock(_lock)
{
_multicastDelegate += del;
}
}
public void Go()
{
_multicastDelegate.Invoke(this);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我在上面的示例中添加了锁,但这实际上不是我的问题的重点。
我试图更好地了解保存调用列表的数组是否是线程安全的。坦白说,我不清楚这是如何组合在一起的,可以提供一些帮助。
根据我发现的文档,唯一没有提供真正洞察力的报价如下:
MulticastDelegate具有由一个或多个元素组成的委托链接列表,称为调用列表。调用多播委托时,调用列表中的委托按照它们出现的顺序被同步调用。如果在执行列表期间发生错误,则会引发异常。
https://msdn.microsoft.com/zh-CN/library/system.multicastdelegate.aspx
提前致谢。
我有一系列我想要执行的闭包,并以安全的方式删除每个项目.
如果我只是这样做:
array.forEach { $0() }
array.removeAll()
Run Code Online (Sandbox Code Playgroud)
项目可能在执行forEach和removeAll执行之间偷偷摸摸,所以我可能会删除在前一行中没有执行的元素.
这样的事情会更安全吗?
extension Array {
mutating func removeEach(handler: @escaping (Element) -> Void) {
enumerated().forEach { handler(remove(at: $0.offset)) }
}
}
Run Code Online (Sandbox Code Playgroud)
有没有一种安全的方法以算法的方式执行此操作而不是使用线程锁?
我有一个结构:
type cache struct {
cap int
ttl time.Duration
items map[interface{}]*entry
heap *ttlHeap
lock sync.RWMutex
NoReset bool
}
Run Code Online (Sandbox Code Playgroud)
它实现的接口:
type Cache interface {
Set(key, value interface{}) bool
Get(key interface{}) (interface{}, bool)
Keys() []interface{}
Len() int
Cap() int
Purge()
Del(key interface{}) bool
}
Run Code Online (Sandbox Code Playgroud)
函数返回单例:
func Singleton() (cache *Cache) {
if singleton != nil {
return &singleton
}
//default
singleton.(cache).lock.Lock()
defer singleton.(cache).lock.Unlock()
c := New(10000, WithTTL(10000 * 100))
return &c
}
Run Code Online (Sandbox Code Playgroud)
我不确定哪种类型应该是我的singleton:
当var singleton cache我无法检查零
如果var singleton …
我想知道在特定情况下是否像这样,我们有bool标志,表明是否有一些服务可用:
private bool isAvailable;
private void foo()
{
if(isAvailable)
{
isAvailable = false;
DoSomething();
isAvailable = true;
}
}
Run Code Online (Sandbox Code Playgroud)
在多线程环境中将bool字段设置为volatile是否足够,或者使用锁甚至是Monitor更好.
在这种特定情况下,如果此时服务不可用,则不需要等待它再次可用.
我在网上看到了下面的代码,它说"代码不是线程安全的".我不明白为什么?因为,以下每个线程运行getList都不会让任何其他线程到达getList().
public class MyClass {
private List<String> list;
public static void main (String[] args) throws InterruptedException {
MyClass obj = new MyClass();
Thread thread1 = new Thread(() -> {
System.out.println("thread1 : " + System.identityHashCode(obj.getList()));
});
Thread thread2 = new Thread(() -> {
System.out.println("thread2 : " + System.identityHashCode(obj.getList()));
});
thread1.start();
thread2.start();
}
private List<String> getList () {
if (list == null) {
list = new ArrayList<>();
}
return list;
}
}
Run Code Online (Sandbox Code Playgroud) 我知道int128_tC和C++中存在一个类型.
如果我有两个线程,一个从包含这个128位整数的存储器位置读取,另一个正在写入它.
是否有可能将此值写为两个64位整数写入,还是一个128位整数写入?
考虑我们有这样的类:
class A {
public B b;
public void someFunc() { // called sometime
b = new B();
}
}
Run Code Online (Sandbox Code Playgroud)
类B的构造函数分配一些内部变量。
现场b是不是线程安全的在这个意义上另一个线程可以查看b不可─ null当B构造尚未完成。(someFunc执行期间)
我的问题是:从逻辑角度看,构造函数还没有完成怎么办?
对我来说,这种重新排序是不可思议的。
thread-safety ×10
c# ×4
.net ×3
java ×3
algorithm ×1
arrays ×1
c ×1
c++ ×1
casting ×1
concurrency ×1
go ×1
int128 ×1
java-stream ×1
nonblocking ×1
queue ×1
singleton ×1
swift ×1
swift4 ×1