thread error

Hello i have written a program with threads and its doing some weird things i dont understand. i think its an error somewhere but i don't know where could someone explain what's going on ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "stdafx.h"
#include <SFML/System.hpp>
#include <iostream>

int x=0;

void threadfction(void * UserData) {
	for (int j=0;j<100;j+=10) {
		x+=j;
		std::cout<<x<<std::endl;
	}
}


int main () {
	sf::Thread Thread(&threadfction);
	Thread.Launch();

	for (int i=0;i<10;i++) {
		x+=i;
		std::cout<<x<<std::endl;
	}
	system("pause");
	return 0;
}


this is my output which is totally different from what i expected

0
1
3
6
10
15
21
28
36
45
45
55
75
105
145
195
255
325
405
495
Well it is quite normal. What do you have problems with?
i expected an answer like

1
11
12
22
23
33
34
44
45
55
56
66
67
77
Your two threads are reading and writing to the same object (the global variable x) without synchronization. This is a form of undefined behavior known as "data race". Anything at all can happen.

In addition, of course, they are running at the same time, so there is no reason after some thread prints 1, to expect the main thread to be the next to add ten and to print 11 while your second thread would wait.
so using a mutex would solve the problem or not ? or do i have to do something else to avoid that data race ?
i used this code now and it still doesnt really work :/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int x=0;
sf::Mutex GlobalMutex; 


class MyThread : public sf::Thread {
private:

	virtual void Run() {
		GlobalMutex.Lock();

		for (int j=0;j<100;j+=10) {
			x+=j;
			std::cout<<x<<std::endl;
		}
		GlobalMutex.Unlock();
	}
};	


int main () {
	MyThread Thread;

	Thread.Launch();

	GlobalMutex.Lock();

	for (int i=0;i<10;i++) {
		x+=i;
		std::cout<<x<<std::endl;
	}

	GlobalMutex.Unlock();

	system("pause");
	return 0;
}
Last edited on
That eliminates the error, but it doesn't make it print what you expected, of course, since it has no possible way to do so: as written, it will either print the ten numbers from the main thread, then the ten numbers from the second thread, or the other way around.

To produce the output of 1, 11, 12, 22, 23, 33, ..., your threads need to communicate: the second thread should begin waiting for the message from the main thread. the main thread should increment x and print "1" and then message the second thread and begin waiting for the message from the second thread. The second thread, once the message comes, can then add 10 to x, print 11, message the main thread and begin waiting for the message from the main thread, and so on. I don't know SFML (does it have semaphores?), but in plain C++ this can be done with condition variables and mutexes.
how can threads communicate when they are locked by a mutex? o:
in plain C++, it could look like this (note I had to change what your loops do to x, in order to get the output you seem to expect)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

int x = 0;
int turn = 1; // 1  == main's turn, 0 == thread's turn
std::mutex m;
std::condition_variable cv;

void threadFunction()
{
    for(int j = 0; j < 10; ++j)
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return turn == 0;});
        x += 10;
        std::cout << x << '\n';
        turn = 1;
        cv.notify_one();
    }
}

int main()
{
    std::thread t(threadFunction);
    for(int i = 0; i < 10; ++i)
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return turn == 1;});
        ++x;
        std::cout << x << '\n';
        turn = 0;
        cv.notify_one();
    }
    t.join();
}
$ ./test
1
11
12
22
23
33
34
44
45
55
56
66
67
77
78
88
89
99
100
110
Topic archived. No new replies allowed.