C # multithreading

I am trying to run the following program from a book.

The author claims that the result "must be"

1000

2000

....

10,000

if you run the program on a regular processor, but on a multiprocessor computer it may be

999

1998

...

9998

using the normal increment method (number + = 1), but using increments intelocked, as shown in the program, solves the problem (i.e. you get the first result)

Now I have 3 questions. First, why am I not using normal growth in the inner loop [i ++ instead of Interlocked.Increment (ref i)]. Why did the author choose another method?

Secondly, what purpose does Thread.Sleep (1000) have in context. When I comment on this line, I get the second output, even if I use the Interlocked method to increase the number.

Thirdly, I get the correct output even when using the usual increment method [number + = 1] if I do not comment on the Thread.Sleep (1000) line and the second output if I do it.

Now I run the program on the Intel (R) Core i7 Q820 processor, if that matters

static void Main(string[] args) { MyNum n = new MyNum(); for (int a = 0; a < 10; a++) { for (int i = 1; i <= 1000; Interlocked.Increment(ref i)) { Thread t = new Thread(new ThreadStart(n.AddOne)); t.Start(); } Thread.Sleep(1000); Console.WriteLine(n.number); } } class MyNum { public int number = 0; public void AddOne() { Interlocked.Increment(ref number); } } 
+4
source share
3 answers

The dream is simple - let the threads end before looking at the result. This is not a very good answer, although although they should finish in a second, there is no guarantee that they really do.

The need for a blocked increment in the MyNum class is understandable - there are 1000 threads trying to set the number, without protection it would be quite possible for someone to read the number, then the second to read it, and then return it first, and then put the second back, destroying the change made first. Please note that such FAR errors are more likely when there are multiple cores, otherwise this can only happen if the thread switch arrives at the wrong time.

I do not understand why I should be protected.

Edit: you get the same result because the code runs too fast. A thread runs faster than it was created, so they do not start at the same time.

Try:

 public void AddOne() { int x = number + fibnocci(20) + 1 - fibnocci(20); } private int fibnocci(int n) { if (n < 3) return 1 else return fibnocci(n - 1) + fibnocci(n - 2); } 

(hope the optimizer is not good enough to kill this extra code)

+3
source

The code is actually rather strange. Since Thread t declared locally at each iteration, it may be garbage collected by .NET because the link does not exist for the thread. Anyway...

To answer the first question, I do not see the need for Interlocked.Increment(ref i) . The main thread is the only thread that touches i . Using i++ here is not a problem.

For the second question, there is Thread.Sleep(1000) to give the program enough time to complete all threads. Your i7 (quad core with hyperthread) is likely to quickly complete each element.

On the third question, with the same result, number += 1 not guaranteed. Two cores can read the same digit and increment the digits to the same value (i.e. 1001, 1001).

Finally, I'm not sure if you are running the program in debug mode. Building a program in release mode can give you various behaviors and side effects that a multi-threaded program should perform.

+1
source

if you comment out the thread.sleep line, there is a good chance that the threads will not be completed before the print line ... in this case you will see a number less than the β€œcorrect” output, but not because the incrementer was not atomic.

In a true multi-core system, non-atomic actions are possible. You may be doing too few iterations to see a collision.

+1
source

All Articles