我看过他们在无数块的C#代码都被使用了,我想知道何时使用i++或++i(i为某数量的变量一样int,float,double,等).谁知道这个?
灵感来自这个问题:在复杂性分析中,为什么++被认为是2个操作?
请使用以下伪代码:
class test
{
int _counter;
void Increment()
{
_counter++;
}
}
Run Code Online (Sandbox Code Playgroud)
在x86架构上,这会被认为是线程安全的吗?还有更多的是Inc/Dec装配说明线程安全吗?
如果我运行此测试:
var r = new Random();
var ints = new int[13];
Parallel.For(0, 2000000, i => {
var result = r.Next(1, 7) + r.Next(1, 7);
ints[result] += 1;
});
Run Code Online (Sandbox Code Playgroud)
我得到以下结果:
2: 92,14445
3: 0,41765
4: 0,62245
5: 0,82525
6: 1,04035
7: 1,25215
8: 1,0531
9: 0,8341
10: 0,6334
11: 0,4192
12: 0,2109
Run Code Online (Sandbox Code Playgroud)
当我使用常规For:
for (int i = 0; i < 2000000; i++) {
var result = r.Next(1, 7) + r.Next(1, 7);
ints[result] += 1;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
2: 2,7797
3: 5,58645
4: …Run Code Online (Sandbox Code Playgroud) 假设您有以下代码
var dictionary = new Dictionary<int, object>(capacity: 2500);
var uniqueKeys = Enumerable.Range(0, 1000).ToArray();
Parallel.ForEach(uniqueKeys, key => dictionary[key] = new object());
Run Code Online (Sandbox Code Playgroud)
请注意,所有键都是唯一的,并且字典容量远远超过键的数量。
问题:是否有任何条件会导致此代码不成功?
鉴于当前的实施情况Dictionary<,> 并且不假设未来假设的内部变化,您能提供任何不安全访问的证据吗?
备注:这不是.Net中的线程安全Dictionary<int,int>或a 的线程安全的Dictionary<TKey, TValue>重复,我不需要任何人告诉我ConcurrentDictionary,等等。
我有多个线程使用"++"或" - "操作访问单个Int32变量.
我们是否需要在访问之前锁定,如下所示?
lock (idleAgentsLock)
{
idleAgents--; //we should place it here.
}
Run Code Online (Sandbox Code Playgroud)
或者如果我不进行锁定会有什么后果?
有人可以解释下面的代码如何工作?
static int index = 0;
public static int GetNextIndex()
{
return index++;
}
Run Code Online (Sandbox Code Playgroud)
我假设,因为增量操作发生在return语句之后,变量'index'将永远不会增加.
但是当使用C#编译器进行测试时,我发现'index'正在增加.
标准编译器如何处理这种情况?
我写这个实验是为了向某人证明使用多个线程同时访问共享数据是一个很大的禁忌。令我惊讶的是,无论我创建了多少线程,我都无法创建并发问题,并且该值始终导致平衡值 0。我知道增量运算符不是线程安全的,这就是为什么有方法的原因喜欢Interlocked.Increment()和Interlocked.Decrement()(这里也提到了 ++ 运算符线程安全吗?)。
如果递增/递减运算符不是线程安全的,那么为什么下面的代码执行没有任何问题并且结果达到预期值?
下面的代码段创建了 2,000 个线程。1,000 不断递增,1,000 不断递减,以确保多个线程同时访问数据。更糟糕的是,在普通程序中,您不会有那么多线程。然而,尽管为了造成并发问题而夸大了数字,但该值始终导致平衡值 0。
static void Main(string[] args)
{
Random random = new Random();
int value = 0;
for (int x=0; x<1000; x++)
{
Thread incThread = new Thread(() =>
{
for (int y=0; y<100; y++)
{
Console.WriteLine("Incrementing");
value++;
}
});
Thread decThread = new Thread(() =>
{
for (int z=0; z<100; z++)
{
Console.WriteLine("Decrementing");
value--;
}
});
incThread.Start();
decThread.Start();
}
Thread.Sleep(TimeSpan.FromSeconds(15));
Console.WriteLine(value);
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
我希望有人能给我一个解释,让我知道我编写线程安全软件的所有努力都没有白费,或者这个实验在某些方面存在缺陷。我也尝试过所有线程递增并使用 ++i …
在大多数情况下double,decimal64位系统上的类型更新是原子操作,因为这些类型是64位.(十进制是128位,所以这是错误的,感谢您的评论)
但是当我更新double?并decimal?输入64位系统时它会是原子的吗?什么是大小double?和decimal?
我知道原子性并不能保证,尽管我仍然感兴趣,如果这种更新在一般情况下是原子的.
我正在使用遗传算法构建优化程序.我使用Parallel.For来减少时间.但它导致了一个问题,在下面的代码中是相同的:
class Program
{
static void Main(string[] args)
{
int j=0;
Parallel.For(0, 10000000, i =>
{
j++;
});
Console.WriteLine(j);
Console.ReadKey();
}
}
Run Code Online (Sandbox Code Playgroud)
每次我运行上面的程序时,它会在0到10000000之间写入不同的j值.我猜它不会等待所有迭代完成.它传递到下一行.我该怎么解决这个问题?任何帮助将不胜感激.谢谢.
版本:Interlocked.Increment(ref j); 子句解决了意外的结果,但是当我与正常循环比较时,此操作会导致大约10倍的时间.