473,769 Members | 6,499 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

strange threading context

This is my problem:

I have two classes A and B:

class A
{
void methodA();
}

class B
{

void methodB();

struct S
{
int Size;
};

S & getMyStruct();

S MyStruct;

}
methodA and methodB get executed in two different threads concurrently.
They both access the variable Size in the structure MyStruct of type S.
methodA gets a reference to this struct by calling getMyStruct which returns
a reference
to it.
Here comes the strange part:
if methodB alters the value of Size from 0 to 1, this change doesn't get
reflected in methodA - methodA
still reads a 0. The access to the struct MyStruct is sychronized by a
mutex.

Whats going on here? Why are the changes of Size by thread executing methodB
not visible to the thread executing methodA.
I thought that struct myStruct lies in the context of both threads/methods.

Regards

A.Gallus

Aug 16 '08 #1
5 1565
A.Gallus wrote:
This is my problem:

I have two classes A and B:

class A
{
void methodA();
}

class B
{

void methodB();

struct S
{
int Size;
};

S & getMyStruct();

S MyStruct;

}
methodA and methodB get executed in two different threads concurrently.
They both access the variable Size in the structure MyStruct of type S.
methodA gets a reference to this struct by calling getMyStruct which
returns a reference
to it.
Here comes the strange part:
if methodB alters the value of Size from 0 to 1, this change doesn't get
reflected in methodA - methodA
still reads a 0. The access to the struct MyStruct is sychronized by a
mutex.
Show the code. If you don't have an appropriate memory barrier each
thread/core may have the local copy in a register.

--
Ian Collins.
Aug 16 '08 #2
"A.Gallus" <uh**@rz.uni-karlsruhe.dewro te in message
news:g8******** **@news2.rz.uni-karlsruhe.de...
This is my problem:

I have two classes A and B:

class A
{
void methodA();
}

class B
{

void methodB();

struct S
{
int Size;
};

S & getMyStruct();

S MyStruct;

}
methodA and methodB get executed in two different threads concurrently.
They both access the variable Size in the structure MyStruct of type S.
methodA gets a reference to this struct by calling getMyStruct which
returns a reference
to it.
Here comes the strange part:
if methodB alters the value of Size from 0 to 1, this change doesn't get
reflected in methodA - methodA
still reads a 0. The access to the struct MyStruct is sychronized by a
mutex.
Well, let me try to read your mind and see if I can make a better model in
the form of fully compliable code:

code listing 1 with a race-condition!
_______________ _______________ _______________ _______________ __________
#include <cstdio>
#include <pthread.h>
class mutex_guard {
pthread_mutex_t * const m_mutex;

public:
mutex_guard(pth read_mutex_t* const mutex)
: m_mutex(mutex) {
pthread_mutex_l ock(m_mutex);
}

~mutex_guard() {
pthread_mutex_u nlock(m_mutex);
}
};
class A {
public:
void methodA();
};

class B {
friend class A;

struct S {
int Size;
S() : Size() {}
};

S MyStruct;

S& getMyStruct() {
return MyStruct;
}

static pthread_mutex_t g_mutex;

public:
void methodB();
};
pthread_mutex_t B::g_mutex = PTHREAD_MUTEX_I NITIALIZER;
static B g_global_instan ce_of_B;
static A g_global_instan ce_of_A;
void A::methodA() {
mutex_guard lock(&B::g_mute x);
std::printf("A: :methodA() - B::MyStruct::Si ze == %d\n",
g_global_instan ce_of_B.getMySt ruct().Size);
}
void B::methodB() {
mutex_guard lock(&B::g_mute x);
MyStruct.Size = 1;
std::printf("B: :methodB() - B::MyStruct::Si ze == %d\n",
g_global_instan ce_of_B.getMySt ruct().Size);
}
extern "C" void* thread_1(void*) {
g_global_instan ce_of_A.methodA ();
return NULL;
}
extern "C" void* thread_2(void*) {
g_global_instan ce_of_B.methodB ();
return NULL;
}
int main() {
pthread_t tid[2];
pthread_create( &tid[0], NULL, thread_1, NULL);
pthread_create( &tid[1], NULL, thread_2, NULL);
for (int i = 0; i < 2; ++i) {
pthread_join(ti d[i], NULL);
}
return 0;
}

_______________ _______________ _______________ _______________ __________
Okay, this program can run 3 ways... The first is that thread_1 runs first
and therefore misses the update. Second, thread_2 runs first and the update
is observed when thread_1 runs. The third is that they run together and race
through in which anything can happen. For instance, if thread_1 hits the
mutex first, then the update will not be observed.

If you want to ensure that thread_1 will ALWAYS see the mutation generated
by thread_2, well, you need someway to make sure that thread_2 runs first. A
simple and niave soultion is to use a simple semaphore. Think of this:
code listing 2 without a race-condition!
_______________ _______________ _______________ _______________ __________
#include <cstdio>
#include <pthread.h>
#include <semaphore.h>
class mutex_guard {
pthread_mutex_t * const m_mutex;

public:
mutex_guard(pth read_mutex_t* const mutex)
: m_mutex(mutex) {
pthread_mutex_l ock(m_mutex);
}

~mutex_guard() {
pthread_mutex_u nlock(m_mutex);
}
};
class A {
public:
void methodA();
};

class B {
friend class A;

struct S {
int Size;
S() : Size() {}
};

S MyStruct;

S& getMyStruct() {
return MyStruct;
}

static pthread_mutex_t g_mutex;

public:
void methodB();
};
pthread_mutex_t B::g_mutex = PTHREAD_MUTEX_I NITIALIZER;
static B g_global_instan ce_of_B;
static A g_global_instan ce_of_A;
void A::methodA() {
mutex_guard lock(&B::g_mute x);
std::printf("A: :methodA() - B::MyStruct::Si ze == %d\n",
g_global_instan ce_of_B.getMySt ruct().Size);
}
void B::methodB() {
mutex_guard lock(&B::g_mute x);
MyStruct.Size = 1;
std::printf("B: :methodB() - B::MyStruct::Si ze == %d\n",
g_global_instan ce_of_B.getMySt ruct().Size);
}
extern "C" void* thread_1(void* state) {
sem_t* const sem = (sem_t*)state;
sem_wait(sem);
g_global_instan ce_of_A.methodA ();
return NULL;
}
extern "C" void* thread_2(void* state) {
sem_t* const sem = (sem_t*)state;
g_global_instan ce_of_B.methodB ();
sem_post(sem);
return NULL;
}
int main() {
pthread_t tid[2];
sem_t sem;
sem_init(&sem, 0, 0);
pthread_create( &tid[0], NULL, thread_1, &sem);
pthread_create( &tid[1], NULL, thread_2, &sem);
for (int i = 0; i < 2; ++i) {
pthread_join(ti d[i], NULL);
}
sem_destroy(&se m);
return 0;
}

_______________ _______________ _______________ _______________ __________
Now, thread_1 will always see the mutation made by thread_2. Period, end of
story. thread_1 will ALWAYS output:
A::methodA() - B::MyStruct::Si ze == 1

Whats going on here? Why are the changes of Size by thread executing
methodB not visible to the thread executing methodA.
I thought that struct myStruct lies in the context of both
threads/methods.
Perhaps the thread in which methodA gets invoked happens to execute first,
thus it has no chance to observe the mutation made by the thread which
invokes methodB.

Aug 17 '08 #3
When I create MyStruct on the heap (with new) instead writing it as a
reference class member everything works fine:

S * getMyStruct();

S * MyStruct;

It seems to me that both classes are working on another copy of MyStruct
when I don't use
new(). I doubt that I have a race condition, unfortunately the code is way
to long to post it here.

Thx guys!

Regards

A.Gallus
Aug 17 '08 #4
A.Gallus wrote:
When I create MyStruct on the heap (with new) instead writing it as a
reference class member everything works fine:

S * getMyStruct();

S * MyStruct;

It seems to me that both classes are working on another copy of MyStruct
when I don't use
new(). I doubt that I have a race condition, unfortunately the code is
way to long to post it here.
Then post a simplified example. You'll probably solve the problem
writing it.

--
Ian Collins.
Aug 17 '08 #5
A.Gallus schrieb:
When I create MyStruct on the heap (with new) instead writing it as a
reference class member everything works fine:
You had it as reference class member instead of as value member?
S * getMyStruct();

S * MyStruct;

It seems to me that both classes are working on another copy of MyStruct
when I don't use
new(). I doubt that I have a race condition, unfortunately the code is
way to long to post it here.
You could check that by printing the address of the member and the
address of the containing class in both threads. If the addresses are
not equal, you are working with two distinct copies.

--
Thomas
Aug 17 '08 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
4907
by: Joe Wong | last post by:
Hi, Is there any way to increase/decrease a thread priority in Python? Best regards, -- Wong
4
9077
by: MJB | last post by:
I never get the above exception in Windows 2k. It only happens in Windows XP, which is the first oddity. My application is multi-threaded and I use the webbrowser control and media player. The exception normally occurs when I open the browser control or media control, but sometimes it just occurs randomly. I was thinking first that it was some sort of build difference with the COM interop components, but I re-referenced and rebuilt...
4
6106
by: Oz | last post by:
This is long. Bear with me, as I will really go through all the convoluted stuff that shows there is a problem with streams (at least when used to redirect stdout). The basic idea is that my application (VB.NET) will start a process, redirect its stdout and capture that process' output, displaying it in a window. I've written a component for this, and a test application for the component. It allows me to specify a command to execute,...
0
1079
by: sqcliu | last post by:
I encounter a strange problem using platform invoke using C#. The senario is this: I have a dll which uses a 3rd party static link library (lib). Inside the lib, there are some C structures defined by not exposed to user, in the dll, that data type can be treated as an opaque type. I use C# and unamanaged C++ to write two programs to use the dll. The C++ version works perfectly, but the C# version always get some exception (Object...
4
2938
by: hazz | last post by:
If I successfully run a VS.NET app which includes the following; ************************** APP 1 **************************** m_iIdnt = new System.Security.Principal.GenericIdentity(t.UserName,"MyAuthentication"); //user and My authentication type added to Identity string roles = {"Chief Cook and Bottle Washer", "Master Gardener"};
5
2366
by: Andrew Lippitt | last post by:
What gaurantees are there in the way of which thread the events are called from. I've seen: Thread A Begin Thread B Begin Thread A End Thread A End That seems to indicate that Begin and End can't be assumed to be called from the same thread, but can I assume that the Begin will happen on the same thread that executes the request?
5
1556
by: Carl J. Van Arsdall | last post by:
Hi everyone, I'm trying to use the threading module with python 2.2 and I have some questions regarding python's threading. 1. Who schedules which threads run and when? Is this something left up to the operating system or does python provide a mechanism for this? 2. I've read that python threads don't like to allow other threads to run except in certain situations, these would be situations where there is sleep or I/O happening, is...
2
3861
by: Spam Catcher | last post by:
Anyone know what this error means? The Undo operation encountered a context that is different from what was applied in the corresponding Set operation. The possible cause is that a context was Set on the thread and not reverted(undone). It seems to pop up when I use nSoftware's IPDaemon...
0
1140
by: LoneTiger | last post by:
Hi everyone, I've got a smaller problem which I can't get around of. I've seen some quite usefull answers around and was hoing someone might be able to help. What I'm working on is a web application, which will be used for internal web service testing. All of it runs on c# .net 2.0. Currently I wanted to do some stress testing using multi-threading. Problem is I'm using threading iside web context. To further complicate...
0
9423
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10211
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10045
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9863
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7406
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5298
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3958
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3561
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2815
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.