Concurrency in Linux: Alternate access of two threads in critical zone - linux

I'm new with the concepts of concurrency and threads in Linux and I tried to solve a relative simple problem. I create two threads which run the same function which increment a global variable. What I really want from my program is to increment that variable alternatively, namely ,say in each step the thread that increment that variable prints to the screen a message , so the expected output should look like:
Thread 1 is incrementing variable count... count = 1
Thread 2 is incrementing variable count... count = 2
Thread 1 is incrementing variable count... count = 3
Thread 2 is incrementing variable count... count = 4
and so on.
I tried an implementation with a semaphore which ensures mutual exclusion, but nonetheless the result resembles this:
Thread 2 is incrementing variable count... count = 1
Thread 2 is incrementing variable count... count = 2
Thread 2 is incrementing variable count... count = 3
Thread 2 is incrementing variable count... count = 4
Thread 2 is incrementing variable count... count = 5
Thread 1 is incrementing variable count... count = 6
Thread 1 is incrementing variable count... count = 7
Thread 1 is incrementing variable count... count = 8
Thread 1 is incrementing variable count... count = 9
Thread 1 is incrementing variable count... count = 10
My code looks like:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
int count = 0;
sem_t mutex;
void function1(void *arg)
{
int i = 0;
int *a = (int*) arg;
while (i < 10)
{
sem_wait(&mutex);
count++;
i++;
printf("From the function : %d count is %d\n",*a,count);
sem_post(&mutex);
}
}
int main()
{
pthread_t t1,t2;
int a = 1;
int b = 2;
pthread_create(&t1,NULL,(void *)function1,&a);
pthread_create(&t2,NULL,(void *)function1,&b);
sem_init(&mutex,0,1);
pthread_join(t2,NULL);
pthread_join(t1,NULL);
sem_destroy(&mutex);
return 0;
}
My big question is now , how do I achieve this alternation between threads? I got mutual exclusion , but the alternation is still missing. Maybe I lack a good insight of semaphores usage, but I would be very grateful if someone would explain that to me. (I have read several courses on this topic ,namely,Linux semaphores,concurrency and threads, but the information there wasn't satisfactory enough)

Mutex locks don't guarantee any fairness. This means that if thread 1 releases it and then attempts to get it again, there is no guarantee that it won't - it's just guarantees that no two pieces of code can be running in that block at the same time.
EDIT: Removed previous C-style solution because it was probably incorrect. The question asks for a synchronization solution.
If you really want to do this correctly you would use something called a monitor and a guard (or condition variable). I'm not too familiar with C and pThreads so you would need to take a look how to do it with that, but in Java it would look something like:
public class IncrementableInteger {
public int value;
#Override
public String toString() {
return String.valueOf(value);
}
}
#Test
public void testThreadAlternating() throws InterruptedException {
IncrementableInteger i = new IncrementableInteger();
Monitor m = new Monitor();
Monitor.Guard modIsZeroGuard = new Monitor.Guard(m) {
#Override public boolean isSatisfied() {
return i.value % 2 == 0;
}
};
Monitor.Guard modIsOneGuard = new Monitor.Guard(m) {
#Override public boolean isSatisfied() {
return i.value % 2 == 1;
}
};
Thread one = new Thread(() -> {
while (true) {
m.enterWhenUninterruptibly(modIsZeroGuard);
try {
if (i.value >= 10) return;
i.value++;
System.out.println("Thread 1 inc: " + String.valueOf(i));
} finally {
m.leave();
}
}
});
Thread two = new Thread(() -> {
while (true) {
m.enterWhenUninterruptibly(modIsOneGuard);
try {
if (i.value >= 10) return;
i.value++;
System.out.println("Thread 2 inc: " + String.valueOf(i));
} finally {
m.leave();
}
}
});
one.start();
two.start();
one.join();
two.join();
}

Related

How to trigger a race condition?

I am researching about fuzzing approaches, and I want to be sure which approach is suitable for Race Condition problem. Therefor I have a question about race condition itself.
Let's suppose we have a global variable and some threads have access to it without any restriction. How can we trigger the existing race condition? Is it enough to run just the function that uses the global variable with several threads? I mean just running the function will trigger race condition anyway?
Here, I put some code, and I know it has race condition problem. I want to know which inputs should give the functions to trigger the corresponding race condition problem.
#include<thread>
#include<vector>
#include<iostream>
#include<experimental/filesystem>
#include<Windows.h>
#include<atomic>
using namespace std;
namespace fs = experimental::filesystem;
volatile int totalSum;
//atomic<int> totalSum;
volatile int* numbersArray;
void threadProc(int startIndex, int endIndex)
{
Sleep(300);
for(int i = startIndex; i < endIndex; i++)
{
totalSum += numbersArray[i];
}
}
void performAddition(int maxNum, int threadCount)
{
totalSum = 0;
numbersArray = new int[maxNum];
for(int i = 0; i < maxNum; i++)
{
numbersArray[i] = i + 1;
}
int numbersPerThread = maxNum / threadCount;
vector<thread> workerThreads;
for(int i = 0; i < threadCount; i++)
{
int startIndex = i * numbersPerThread;
int endIndex = startIndex + numbersPerThread;
if (i == threadCount - 1)
endIndex = maxNum;
workerThreads.emplace_back(threadProc, startIndex, endIndex);
}
for(int i = 0; i < workerThreads.size(); i++)
{
workerThreads[i].join();
}
delete[] numbersArray;
}
void printUsage(char* progname)
{
cout << "usage: " << fs::path(progname).filename() << " maxNum threadCount\t with 1<maxNum<=10000, 0<threadCount<=maxNum" << endl;
}
int main(int argc, char* argv[])
{
if(argc != 3)
{
printUsage(argv[0]);
return -1;
}
long int maxNum = strtol(argv[1], nullptr, 10);
long int threadCount = strtol(argv[2], nullptr, 10);
if(maxNum <= 1 || maxNum > 10000 || threadCount <= 0 || threadCount > maxNum)
{
printUsage(argv[0]);
return -2;
}
performAddition(maxNum, threadCount);
cout << "Result: " << totalSum << " (soll: " << (maxNum * (maxNum + 1))/2 << ")" << endl;
return totalSum;
}
Thanks for your help
There may be many cases of race conditions. One of example for your case:
one thread:
reads commonly accessible variable (1)
increments it (2)
sets the common member variable to resulting value (to 2)
second thread starts just after the first thread read the common value
it read the same value (1)
incremented the value it read. (2)
then writes the calculated value to common member variable at the same time as first one. (2)
As a result
the member value was incremented only by one (to value of 2) , but it should increment by two (to value of 3) since two threads were acting on it.
Testing race conditions:
for your purpose (in the above example) you can detect race condition when you get different result than expected.
Triggerring
if you may want the described situation always to happen for the purpose of - you will need to coordinate the work of two threads. This will allow you to do your testing
Nevertheless coordination of two threads will violate definition race condition if it is defined as: "A race condition or race hazard is the behavior of an electronics, software, or other system where the system's substantive behavior is dependent on the sequence or timing of other uncontrollable events.". So you need to know what you want, and in summary race condition is an unwanted behavior, that in your case you want to happen what can make sense for testing purpose.
If you are asking generally - when a race condition can occur - it depends on your software design (e.g you can have shared atomic integers which are ok to be used), hardware design (eg. variables stored in temporary registers) and generally luck.
Hope this helps,
Witold

How to divide a huge loop into multiple threads and then add result in collection?

I am performing some task in a loop. I need to divide this loop of 1.2 million into multiple threads. Each thread will have some result in list. When all threads are completed I need to add all threads list data into one common list. I can not use ExecutorService. How can I do this?
It should be compatible to jdk 1.6.
This is what I am doing right now:
List<Thread> threads = new ArrayList<Thread>();
int elements = 1200000;
public void function1() {
int oneTheadElemCount = 10000;
float fnum_threads = (float)elements / (float)oneTheadElemCount ;
String s = String.valueOf(fnum_threads);
int num_threads = Integer.parseInt(s.substring(0, s.indexOf("."))) + 1 ;
for(int count =0 ; count < num_threads ; count++) {
int endIndex = ((oneTheadElemCount * (num_threads - count)) + 1000) ;
int startindex = endIndex - oneTheadElemCount ;
if(count == (num_threads-1) )
{
startindex = 0;
}
if(startindex == 0 && endIndex > elements) {
endIndex = elements -1 ;
}
dothis( startindex,endIndex);
}
for(Thread t : threads) {
t.run();
}
}
public List dothis(int startindex, int endIndex) throws Exception {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
for (int i = startindex;
(i < endIndex && (startindex < elements && elements) ) ; i++)
{
//task adding elements in list
}
}
});
thread.start();
threads.add(thread);
return list;
}
I don't know which version of Java you are using but in Java 7 and higher, you can use Fork/Join ForkJoinPool.
Basically,
Fork/Join, introduced in Java 7, isn't intended to replace or compete
with the existing concurrency utility classes; instead it updates and
completes them. Fork/Join addresses the need for divide-and-conquer,
or recursive task-processing in Java programs (see Resources).
Fork/Join's logic is very simple: (1) separate (fork) each large task
into smaller tasks; (2) process each task in a separate thread
(separating those into even smaller tasks if necessary); (3) join the
results.
Citation.
There are various example online that can help with it. I haven't used it myself.
I hope this helps.
For Java6, you can follow this related SO question.

Reading m words from a paragraph from n thread ? C++ multithreading ? Not working?

I want read a paragraph by extracting one word at a time using Multithreading . Each thread should read exactly one word and when paragraph ends they should exit peacefully . I know threads shouldn't be used in this way as there is no advantage in that . But I want to do that so that I can check how threads can work sequentially if required . I tried but it looks like the program is reaching deadlock state and not giving any output at all . There are 11 words in the string and I am using 4 threads .
#include <iostream>
#include <mutex>
#include <sstream>
#include <thread>
#include <chrono>
#include <condition_variable>
using namespace std;
stringstream s("Japan US Canada UK France Germany China Russia Korea India Nepal");
int count = 0;
string word;
condition_variable cv;
mutex m;
int i = 0;
bool check_func(int i,int k)
{
return i == k;
}
void print(int k)
{
while(count < 11) // As there are 11 words
{
unique_lock<mutex> lk(m);
int z = k;
cv.wait(lk,[&]{return check_func(i,z);}); // Line 33
s >> word;
cout<<word<<" ";
i++;
cv.notify_all();
count++;
}
return;
}
int main()
{
thread threads[4];
for(int i = 0; i < 4; i++)
threads[i] = thread(print,i);
for(auto &t : threads)
t.join();
return 0;
}
You need to change this code:
while(count < 11) // As there are 11 words
{
unique_lock<mutex> lk(m);
int z = k;
cv.wait(lk,[&]{return check_func(i,z);}); // Line 33
s >> word;
cout<<word<<" ";
i++;
cv.notify_all();
count++;
}
To this:
int z = k;
while(z < 11) // As there are 11 words
{
unique_lock<mutex> lk(m);
int z = k;
cv.wait(lk,[&]{return check_func(i,z);}); // Line 33
s >> word;
cout<<word<<" ";
i++;
z+=4;
cv.notify_all();
count++;
}
Three things changed in the above: the declaration of z is moved outside of the loop, the condition in the while changed to check z instead of count, and the line z+=4 added. You need to increment z by 4 each time if you want each of your threads to move onto the next word. Also, you need to check z not count because otherwise some of the threads will overshoot and the last word will be printed multiple times (consider the thread that reads the ninth word: if checking on count instead of z it continues on to the next iteration of the loop even though there will be nothing further for it to read).

Error while reading same mem positions on different threads

I have a problem while reading a couple of positions in a double array from different threads.
I enqueue the execution with :
nelements = nx*ny;
err = clEnqueueNDRangeKernel(queue,kernelTvl2of,1,NULL,&nelements,NULL,0,NULL,NULL);
kernelTvl2of has (among other) the code
size_t k = get_global_id(0);
(...)
u1_[k] = (float)u1[k];
(...)
barrier(CLK_GLOBAL_MEM_FENCE);
forwardgradient(u1_,u1x,u1y,k,nx,ny);
barrier(CLK_GLOBAL_MEM_FENCE);
and forwardgradient has the code:
void forwardgradient(global double *f, global double *fx, global double *fy, int ker,int nx, int ny){
unsigned int rowsnotlast = ((nx)*(ny-1));
if(ker<rowsnotlast){
fx[ker] = f[ker+1] - f[ker];
fy[ker] = f[ker+nx] - f[ker];
}
if(ker<nx*ny){
fx[ker] = f[ker+1] - f[ker];
if(ker==4607){
fx[0] = f[4607];
fx[1] = f[4608];
fx[2] = f[4608] - f[4607];
fx[3] = f[ker];
fx[4] = f[ker+1];
fx[5] = f[ker+1] - f[ker];
}
}
if(ker==(nx*ny)-1){
fx[ker] = 0;
fy[ker] = 0;
}
if(ker%nx == nx-1){
fx[ker]=0;
}
fx[6] = f[4608];
}
When I get the contents of the first positions of fx, they are:
-6 0 6 -6 0 6 -6
And here's my problem: when I query fx[ker+1] or fx[4608] on thread with id 4607 I get a '0' (positions second and fifth of the output array), but from other threads I get a '-6' last position of the output array)
Anyone has a clue on what I'm doing wrong, or where I could look to?
Thanks a lot,
Anton
Within a kernel, global memory consistency is only achievable within a single work-group. This means that if a work-item writes a value to global memory, a barrier(CLK_GLOBAL_MEM_FENCE) only guarantees that other work-items within the same work-group will be able to read the updated value.
If you need global memory consistency across multiple work-groups, you need to split your kernel into multiple kernels.

Does this use of release/acquire semantics contain a potential data race?

Consider the following code which I found on http://preshing.com/20120913/acquire-and-release-semantics/ (but I am sure I saw it frequently elsewhere)
Common code:
int A = 0;
std::atomic<int> Ready(0);
Code executed by Thread 1:
A = 42
Ready.store(1, std::memory_order_release);
Code executed by Thread 2:
int r1 = Ready.load(std::memory_order_acquire);
int r2 = A;
It can then be said, that if r1 == 1 then r2 will always be 42 and there is no data race.
My first question is: Does the code nevertheless contain a data race? I mean in the case that r1 == 0. For example, Thread 1 could be preempted half-way through the store to A and then Thread 2 could pick up execution.
I would think that the code for Thread 2 should be rewritten as:
int r1 = Ready.load(std::memory_order_acquire);
int r2 = 0;
if( r1 == 1 ) {
r2 = A;
}
to avoid the potential data race.
Is that true?
Yes, your interpretation is correct: the program contains a data race due to the unconditional read of A. The program is simplified to be a minimal example to demonstrate the workings of acquire-release for the blog: the author discusses only how the memory ordering enforces that the "reader" thread must read 42 from A if it reads 1 from Ready. He doesn't talk about the alternative because it's not germaine.
In a real program, the "reader" thread would probably wait in a loop on Ready to get the desired semantics:
int A = 0;
std::atomic<int> Ready(0);
void write_thread() {
A = 42;
Ready.store(1, std::memory_order_release);
}
void read_thread() {
while (!Ready.load(std::memory_order_acquire))
;
int r2 = A;
assert(r2 == 42);
}
Or use a conditional as in your example:
int A = 0;
std::atomic<int> Ready(0);
void write_thread() {
A = 42;
Ready.store(1, std::memory_order_release);
}
void read_thread() {
while (true) {
if (Ready.load(std::memory_order_acquire)) {
int r2 = A;
assert(r2 == 42);
break;
}
std::cout << "Not ready yet - try again later.\n" << std:flush;
std::this_thread::sleep_for(std::chrono::milliseconds{125});
}
}

Resources