Signal-handling between threads - multithreading

I'm new to concurrent programming and I got around this question I can't really understand what's wrong with, consider the following pseudo-code with x being a shared (conditional) variable initialized with 0:
signal(c)
wait(c)
x = x + 1
signal(c)
What are the possible results for x, running 2 threads (concurrently) in a single processor?

After executing both threads either everything went fine and x = 2 or both "x=x+1" line are executed at the same time and then x = 1 because both thread read the initial value of x as 0 at the same time.

Related

Is this a race condition? If not, can I ever write a program like this (is this program WRONG)?

I'm really new to multi-thread programming.
Really confused about the definition.
Say I have two threads
x, y, z = 0;
Thread 1:
lock(x);
lock(y);
x = y + 1;
unlock(x);
unlock(y);
Thread 2:
lock(x);
lock(z);
z = x + 1;
unlock(x);
unlock(z);
You can see that the value of z is dependent on which thread execute first. If thread 1 happens before thread 2, z = 2; if thread 2 executes first, z = 1. According to many existing answers, e.g. Is this a race condition?, I believe many people think it's not. But the result is unpredictable - depend on thread scheduling still sounds weird to me. It this a semantic mistake? Do people ever write multi-thread programs like this? Thanks for any comments!!

executing a command on a variable used by multiple threads

Given the threading scenario where two threads execute the computation:
x = x + 1 where x is a shared variable
What are the possible results and describe why your answer could happen.
This is a textbook problem from my OS book and I was curious if I needed more information to answer this such as what x is initialized too and how often the threads execute this command or just once. My answer originally was that it could be two possible answers depending on the order that the threads execute them by the OS.
This is a rather simple task, so there isnt probably too much that could go wrong.
The only issue i can immediately think of is if one thread uses on old value of x in its calculation.
eg:
start with x = 2
1) thread A reads x = 2
2) thread B reads x = 2
3) thread A writes x = 2 + 1
x = 3
4) thread B writes x = 2(old value of x) + 1
x = 3 when it should be 4
this would be even more apparent if more than 1 thread reads the value before the first thread writes.

How to achieve 100% cpu usage on windows server 2008

I need to run a very time cost program. This program is made by multi-threads. But when I run it on my sever (windows server 2008 , cpu-E5 2680), it had a same performance with my PC, only with little speed improvement.
So I made a Fib function for testing and I want use all the cores to run this Fib function at the same time with close to 100% CPU usage.
let rec fib n =
if n> 450 then 10
else fib (n+1) + fib (n+2)
let intial (x:BackgroundWorker) =
x.DoWork.Add(fun e ->
ignore(fib 1)
)
x.RunWorkerCompleted.Add(fun e ->())
x
let arr = [|for i = 0 to 7 do yield new BackgroundWorker()|]
let _ = arr |> Array.map intial
while true do
let res =arr |> Array.map (fun e ->
if e.IsBusy then
()
else
e.RunWorkerAsync())
()
When I set only one thread , one core will reach to 100% usage.This does make sense.But when try to increase the number of thread. It show that the CPU usage decrease when the number of thread increase. For example , when I use 8 thread, there will be 8 CPU working with a about 50% usage, and also another one seems to be the thread of the 'While' part. Others seems to be not on working.
So what's wrong here? I really need a demo which can do some parallel computing with a high level CPU usage.
It is likely that your program is limited by the cost of switching threads - it is doing too little useful work. A call to just start job on a thread is 10's of thousands of cycles best case. Calculating the fibonacci of 20 is trivial by comparison.
Remember the fibonacci sequence gets very large, very quickly. You will exceed integer, float and double by the time you reach 450. (I believe the number is about 4.9E93. 64 bit integers run out around 2E19, and doubles loose integer resolution well before that.

basic multithreading

I have the following Interview question:
class someClass
{
int sum=0;
public void foo()
{
for(int i=0; i<100; i++)
{
sum++
}
}
}
There are two parallel threads running through the foo method.
the value of sum at the end will vary from 100 to 200.
the question is why. As I understand only one thread gets a cpu and threads get preempted while running. At what point can the disturbance cause the sum not reaching 200?
The increment isn't atomic. It reads the value, then writes out the incremented value. In between these two operations, the other thread can interact with the sum in complex ways.
The range of values is not in fact 100 to 200. This range is based on the incorrect assumption that threads either take turns or they perform each read simultaneously. There are many more possible interleavings, some of which yield markedly different values. The worst case is as follows (x represents the implicit temporary used in the expression sum++):
Thread A Thread B
---------------- ----------------
x ← sum (0)
x ← sum (0)
x + 1 → sum (1)
x ← sum (1)
x + 1 → sum (2)
⋮
x ← sum (98)
x + 1 → sum (99)
x + 1 → sum (1)
x ← sum (1)
x ← sum (1)
x + 1 → sum (2)
⋮
x ← sum (99)
x + 1 → sum (100)
x + 1 → sum (2)
Thus the lowest possible value is 2. In simple terms, the two threads undo each the other's hard work. You can't go below 2 because thread B can't feed a zero to thread A — it can only output an incremented value — and thread A must in turn increment the 1 that thread B gave it.
The line sum++ is a race condition.
Both threads can read the value of sum as say 0, then each increments its value to 1 and stores that value back. This means that the value of sum will be 1 instead of 2.
Continue like that and you will get a result between 100 and 200.
Most CPU's have multiple cores now. So if we lock a mutex at the beginning of the function foo() and unlock the mutex after the for loop finishes then the 2 threads running on different cores will still yield the answer 200.

Do atomic operations work the same across processes as they do across threads?

Obviously, atomic operations make sure that different threads don't clobber a value. But is this still true across processes, when using shared memory? Even if the processes happen to be scheduled by the OS to run on different cores? Or across different distinct CPUs?
Edit: Also, if it's not safe, is it not safe even on an operating system like Linux, where processes and threads are the same from the scheduler's point of view?
tl;dr: Read the fine print in the documentation of the atomic operations. Some will be atomic by design but may trip over certain variable types. In general, though, an atomic operation will maintain its contract between different processes just as it does between threads.
An atomic operation really only ensures that you won't have an inconsistent state if called by two entities simultaneously. For example, an atomic increment that is called by two different threads or processes on the same integer will always behave like so:
x = initial value (zero for the sake of this discussion)
Entity A increments x and returns the result to itself: result = x = 1.
Entity B increments x and returns the result to itself: result = x = 2.
where A and B indicate the first and second thread or process that makes the call.
A non-atomic operation can result in inconsistent or generally crazy results due to race conditions, incomplete writes to the address space, etc. For example, you can easily see this:
x = initial value = zero again.
Entity A calls x = x + 1. To evaluate x + 1, A checks the value of x (zero) and adds 1.
Entity B calls x = x + 1. To evaluate x + 1, B checks the value of x (still zero) and adds 1.
Entity B (by luck) finishes first and assigns the result of x + 1 = 1 (step 3) to x. x is now 1.
Entity A finishes second and assigns the result of x + 1 = 1 (step 2) to x. x is now 1.
Note the race condition as entity B races past A and completes the expression first.
Now imagine if x were a 64-bit double that is not ensured to have atomic assignments. In that case you could easily see something like this:
A 64 bit double x = 0.
Entity A tries to assign 0x1122334455667788 to x. The first 32 bits are assigned first, leaving x with 0x1122334400000000.
Entity B races in and assigns 0xffeeddccbbaa9988 to x. By chance, both 32 bit halves are updated and x is now = 0xffeeddccbbaa9988.
Entity A completes its assignment with the second half and x is now = 0xffeeddcc55667788.
These non-atomic assignments are some of the most hideous concurrent bugs you'll ever have to diagnose.

Resources