我的目标是:
有一定范围的整数,我必须测试该范围内的每个整数是否随机.我想为此使用多个线程,并使用共享计数器在线程之间平均分配工作.我将计数器设置为开始值,让每个线程取一个数字,增加它,进行一些计算,然后返回一个结果.此共享计数器必须使用锁增加,否则将在要测试的整数范围内存在间隙/重叠.
我不知道从哪里开始.假设我想要12个线程来完成工作,我这样做:
for (int t = 0; t < threads; t++)
{
Thread thr = new Thread(new ThreadStart(startThread));
}
Run Code Online (Sandbox Code Playgroud)
startThread() 是我用于计算的方法.
你能帮帮我吗?我知道我必须使用Interlocked类,但这就是......
可能重复:
使用GreaterThan或LessThan而不是相等的Interlocked.CompareExchange <Int>
我知道Interlocked.CompareExchange仅在值和comparand相等时交换值,
如果不等于实现这样的话,如何交换它们?
if (Interlocked.CompareExchange(ref count, count + 1, max) != max)
// i want it to increment as long as it is not equal to max
{
//count should equal to count + 1
}
Run Code Online (Sandbox Code Playgroud) 我希望两个线程与一个队列一起工作。第一个线程应该每2秒调用一次,第二个线程-每3秒调用一次。这两个线程应同时启动。访问队列的第一个元素时出现问题。两个线程都采用索引为0的元素。有时,它与队列的其他元素一起发生,而不仅仅是第一个元素。我在控制台上有这样的输出:
等等..
这是我使用的代码:
ConcurrentQueue<int> sharedQueue = new ConcurrentQueue<int>();
for (int i = 0; i < 10; i++)
{
sharedQueue.Enqueue(i);
}
int itemCount= 0;
Task[] tasks = new Task[2];
for (int i = 0; i < tasks.Length; i++)
{
// create the new task
tasks[i] = new Task(() =>
{
while (sharedQueue.Count > 0)
{
// define a variable for the dequeue requests
int queueElement;
// take an item from the queue
bool gotElement = sharedQueue.TryDequeue(out …Run Code Online (Sandbox Code Playgroud) 我试图了解Timer如何使用线程池.我写了以下简单的片段.
class Program
{
static private readonly Action Action = () => {
Thread.SpinWait(100 * 10000);
Interlocked.Increment(ref _data);
};
private static volatile int _data;
static private Timer _threadCountChecker = new Timer(
(obj) =>
{
var t = Process.GetCurrentProcess().Threads;
Console.WriteLine("Using {0} threads.", t.Count);
Console.WriteLine(Program._data);
}, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
static void Main(string[] args)
{
var l = new List<Timer>();
for (int i = 0; i < 10; i++)
{
l.Add(new Timer((obj) => Action(), null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)));
}
var exitEvent = new ManualResetEvent(false); …Run Code Online (Sandbox Code Playgroud) 该互锁类提供方便原子操作,如fetch and add和compare and swap.
MSDN说这个类:
为多个线程共享的变量提供原子操作.
我的问题是:为什么称它为" 联锁 "?它应该意味着什么吗?
我尝试使用计算列表的平均值Parallel.For().我决定反对它,因为它比简单的串行版本慢大约四倍.然而我很感兴趣的是它并没有产生与序列结果完全相同的结果,我认为了解原因是有益的.
我的代码是:
public static double Mean(this IList<double> list)
{
double sum = 0.0;
Parallel.For(0, list.Count, i => {
double initialSum;
double incrementedSum;
SpinWait spinWait = new SpinWait();
// Try incrementing the sum until the loop finds the initial sum unchanged so that it can safely replace it with the incremented one.
while (true) {
initialSum = sum;
incrementedSum = initialSum + list[i];
if (initialSum == Interlocked.CompareExchange(ref sum, incrementedSum, initialSum)) break;
spinWait.SpinOnce();
}
});
return sum / list.Count;
} …Run Code Online (Sandbox Code Playgroud) 我正在开发一个使用共享内存和互锁功能的系统.
我们假设我有volatile unsigned int n, a, b.我想原子地执行以下伪代码:
if (a <= n && n < b)
{
n++;
}
else
{
//Do nothing
}
Run Code Online (Sandbox Code Playgroud)
我该怎么办?你可以一起使用多个互锁功能吗?
LONG __cdecl InterlockedCompareExchange(
__inout LONG volatile *Destination,
__in LONG Exchange,
__in LONG Comparand
);
Run Code Online (Sandbox Code Playgroud)
返回值
函数返回Destination参数的初始值。
只是好奇。
为什么InterlockedCompareExchange返回初始值?他们这样做是有原因的吗?
我在一行代码中发现了一个编译器错误:
int thisIndex = Interlocked.Increment(ref messagesIndex) & indexMask;
Run Code Online (Sandbox Code Playgroud)
定义是:
static int messagesIndex = -1;
public const int MaxMessages = 0x10000;
const int indexMask = MaxMessages-1;
Run Code Online (Sandbox Code Playgroud)
messagesIndex 任何其他代码行都不会访问它.
如果我在一个线程中运行该代码数十亿次,我就不会收到任何错误.
如果我在几个线程上运行上面的行,我得到两次相同的数字,并且每隔1x-000次跳过另一个数字.
我在6个线程上运行了数十亿次而没有出现错误:
int thisIndex = Interlocked.Increment(ref messagesIndex);
Run Code Online (Sandbox Code Playgroud)
结论和问题
似乎Interlocked.Increment()按照预期自己的工作,但是Interlocked.Increment()&indexMask不:-(
知道我怎么能让它一直正常工作,而不仅仅是99.99%?
我试图分配Interlocked.Increment(ref messagesIndex)一个易变的整数变量并"& indexMask"对该变量进行操作:
[ThreadStatic]
volatile static int nextIncrement;
nextIncrement = Interlocked.Increment(ref mainIndexIncrementModTest);
indexes[testThreadIndex++] = nextIncrement & maskIncrementModTest;
Run Code Online (Sandbox Code Playgroud)
它会导致同样的问题,就像我在1行中写它一样.
拆卸
也许有人可以从反汇编中猜出编译器引入了什么问题:
indexes[testThreadIndex++] = Interlocked.Increment(ref mainIndexIncrementTest);
0000009a mov eax, dword ptr [ebp-48h]
0000009d mov …Run Code Online (Sandbox Code Playgroud)