Quick thread safety question

SunnyD

Belgian Waffler
Jan 2, 2001
32,674
146
106
www.neftastic.com
I'm writing up something that will spawn worker threads as needed, and they will just keep on going until they finish or the app signals a shutdown. I'm thinking a quick and dirty way is to create a static global flag that the worker threads will READ each pass in their loop to determine whether to prematurely terminate or not. The flag will only ever be set once - when the parent process is getting ready to shut down. Do I really need to take the time to lock the global and such when I don't really care if it takes a few extra passes through the thread's loop before it notices the flag was set?
 
Sep 29, 2004
18,656
67
91
Originally posted by: SunnyD
I'm writing up something that will spawn worker threads as needed, and they will just keep on going until they finish or the app signals a shutdown. I'm thinking a quick and dirty way is to create a static global flag that the worker threads will READ each pass in their loop to determine whether to prematurely terminate or not. The flag will only ever be set once - when the parent process is getting ready to shut down. Do I really need to take the time to lock the global and such when I don't really care if it takes a few extra passes through the thread's loop before it notices the flag was set?

Be safe and lock it.
 

smack Down

Diamond Member
Sep 10, 2005
4,507
0
0
You don't need to lock it. Depending on the number of threads and what they do it could become a bottle neck if you lock it.
 

brandonb

Diamond Member
Oct 17, 2006
3,731
2
0
What language are you using?

Look up:

CreateEvent
WaitForMultipleObject
SetEvent

If you are using C++/Windows.

The idea is this:

Create an Event for Shutdown.
Create an Event for each worker thread:

When the thread starts up have it:

Do
event = WaitForMultipleObjects(on shutdown event and Event to trigger worker thread)
select(event)
{
case shutdown
break;
case trigger
// do work
}
Loop

From Main thread

SetEvent(shutdown) or SetEvent(trigger worker thread event)

When you want the worker thread to start or shutdown, you just trigger the right event.

Any worker thread waiting with a shutdown will be fired by the single shutdown event.

No mutex/locking is necessary. Those commands are specifically written for multi threaded coding.

That is for a fire and forget method. To determine if someone shut down during a long process, you can do a "WaitForSingleObject" on the shutdown event, and if it triggers, exit out. Just Specify the Timeout as 0... So it will return immediately if the event was triggered or not.
 

smack Down

Diamond Member
Sep 10, 2005
4,507
0
0
I don't think that would work for what the OP wants. Your method requires that the thread wait for either a trigger or a shutdown event. The op want a thread that is already in the middle of its task to exit and therefor waiting until it gets back to your event loop may take for ever.



 

brandonb

Diamond Member
Oct 17, 2006
3,731
2
0
Originally posted by: smack Down
I don't think that would work for what the OP wants. Your method requires that the thread wait for either a trigger or a shutdown event. The op want a thread that is already in the middle of its task to exit and therefor waiting until it gets back to your event loop may take for ever.

Yep. The last paragraph I mention that. Just do the "WaitForSingleObject" on the shutdown event with a timeout of 0 to figure out if the shutdown was called. You can do that inside a for loop or whatever. Like:

Do
event = WaitForMultipleObjects(on shutdown event and Event to trigger worker thread)
select(event)
{
case shutdown
break;
case trigger
// do work

for(i = 1; i<100000000000000000000; i++)
{
event = WaitForSingleObject(on shutdown event)
if event = fired then break out

// do stuff

}

}
Loop
 

SunnyD

Belgian Waffler
Jan 2, 2001
32,674
146
106
www.neftastic.com
C++, basically I want to avoid overhead of locking the variable just for a read. There's the potential to get a lot of threads checking it simultaneously (we'll say 50-100 threads maybe?), but only the parent process will ever actually WRITE to that variable. And again, it doesn't matter if the thread checks it and it's not set, only to have it set by the time the thread executes its next instruction. The thread can actually complete it's next iteration of the loop before I care that it shuts down, but I do want a way to gracefully shut down the threads.
 

smack Down

Diamond Member
Sep 10, 2005
4,507
0
0
Originally posted by: SunnyD
C++, basically I want to avoid overhead of locking the variable just for a read. There's the potential to get a lot of threads checking it simultaneously (we'll say 50-100 threads maybe?), but only the parent process will ever actually WRITE to that variable. And again, it doesn't matter if the thread checks it and it's not set, only to have it set by the time the thread executes its next instruction. The thread can actually complete it's next iteration of the loop before I care that it shuts down, but I do want a way to gracefully shut down the threads.

That is thread safe is if the write and read operations are atomic. For how you are using it that shouldn't be a problem because you are checking equals/not equals. Just a note but you can have any/all threads set the exit flag and it will still be thread safe. All atomic operations are always thread safe.

You could run into a problem if your flag was either a double or long and you did different things based on its value. On x86 cpus writing to 64 bits of memory is not atomic so if you had xy in the 64 bits before writing ab you could read xb, xy, ay, or ab.

As a side note locking does not force any order it just make non atomic operations atomic. Locking around an operation that is already atomic has no effect on the execution of the program.
 

xtknight

Elite Member
Oct 15, 2004
12,974
0
71
I hope you don't mind the subtle thread hijack but I had a question about threads.

Apparently atomicity or flagging volatility ensures that no two cores can access that same memory address at the same time?

static global __int32 myVar,myVar2,myVar3;

a thread
{
myVar = 5;
myVar2 = 6;
myVar3 = 7;
}

It's said that myVar = 5 is an atomic operation, so does that mean that this whole block is also atomic on a 32-bit CPU?

static global __int32 myVar;

a thread
{
myVar = 4; //line 1
if (myVar) myVar = 6; //line 2
myVar = 5; //line 3
}

If I'm right, the possible collisions in this are:
line 1 vs line 3
line 2 vs line 1
line 2 vs line 3

Or, could line 1 and line 3 never collide among threads because their operations are both atomic, meaning only line 2 is an issue (because line 2 has two operations on it (equality and assignment), making it non-atomic)?

a thread
{
myVar = 4;
myVar = 2;
}

In other words, is the above thread-safe? I basically don't understand why an operation that is atomic means it can not be invoked on two cores at the same exact time. They can't execute that instruction at the exact same time or there is some automatic kind of lock?
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Originally posted by: SunnyD
C++, basically I want to avoid overhead of locking the variable just for a read. There's the potential to get a lot of threads checking it simultaneously (we'll say 50-100 threads maybe?), but only the parent process will ever actually WRITE to that variable. And again, it doesn't matter if the thread checks it and it's not set, only to have it set by the time the thread executes its next instruction. The thread can actually complete it's next iteration of the loop before I care that it shuts down, but I do want a way to gracefully shut down the threads.

1) Declare the variable as volatile (already mentioned above)
2) Don't try anything fancy -- e.g. just set a boolean to true or an int to non-zero -- don't try to read-modify-write the variable

Follow 1 & 2 and you don't need a lock. Even with 50-100 sw threads there will only be 4-32 or so hw threads actually reading at a time, and thats what cache coherence is for.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Originally posted by: xtknight
I hope you don't mind the subtle thread hijack but I had a question about threads.

Apparently atomicity or flagging volatility ensures that no two cores can access that same memory address at the same time?

static global __int32 myVar,myVar2,myVar3;

a thread
{
myVar = 5;
myVar2 = 6;
myVar3 = 7;
}

It's said that myVar = 5 is an atomic operation, so does that mean that this whole block is also atomic on a 32-bit CPU?

static global __int32 myVar;

a thread
{
myVar = 4; //line 1
if (myVar) myVar = 6; //line 2
myVar = 5; //line 3
}

If I'm right, the possible collisions in this are:
line 1 vs line 3
line 2 vs line 1
line 2 vs line 3

Or, could line 1 and line 3 never collide among threads because their operations are both atomic, meaning only line 2 is an issue (because line 2 has two operations on it (equality and assignment), making it non-atomic)?

a thread
{
myVar = 4;
myVar = 2;
}

In other words, is the above thread-safe? I basically don't understand why an operation that is atomic means it can not be invoked on two cores at the same exact time. They can't execute that instruction at the exact same time or there is some automatic kind of lock?


On x86, individual accesses to single memory locations from a single thread are atomic and obey program order semantics. In the example above, there are four operations on variable myVar (which I will assume is 32 bit-sized or smaller):
Line 1: Write 4
Line 2: Read, then (possibly) Write 6
Line 3: Write 5

Each read and write operation is guaranteed to be atomic. However, Line 2 is not atomic, as another thread could write myVar after Line 2's read but before line 2's write.

The lines together, however, are in no way atomic.

Edit: Removed some scary memory consistency details.
 

SunnyD

Belgian Waffler
Jan 2, 2001
32,674
146
106
www.neftastic.com
Originally posted by: degibson
Originally posted by: SunnyD
C++, basically I want to avoid overhead of locking the variable just for a read. There's the potential to get a lot of threads checking it simultaneously (we'll say 50-100 threads maybe?), but only the parent process will ever actually WRITE to that variable. And again, it doesn't matter if the thread checks it and it's not set, only to have it set by the time the thread executes its next instruction. The thread can actually complete it's next iteration of the loop before I care that it shuts down, but I do want a way to gracefully shut down the threads.

1) Declare the variable as volatile (already mentioned above)
2) Don't try anything fancy -- e.g. just set a boolean to true or an int to non-zero -- don't try to read-modify-write the variable

Follow 1 & 2 and you don't need a lock. Even with 50-100 sw threads there will only be 4-32 or so hw threads actually reading at a time, and thats what cache coherence is for.

Exactly, no read-modify-write ever happening here. The worker threads will only ever read the value. Based on what I'm seeing here, sounds like what I thought is valid. Cool!
 
sale-70-410-exam    | Exam-200-125-pdf    | we-sale-70-410-exam    | hot-sale-70-410-exam    | Latest-exam-700-603-Dumps    | Dumps-98-363-exams-date    | Certs-200-125-date    | Dumps-300-075-exams-date    | hot-sale-book-C8010-726-book    | Hot-Sale-200-310-Exam    | Exam-Description-200-310-dumps?    | hot-sale-book-200-125-book    | Latest-Updated-300-209-Exam    | Dumps-210-260-exams-date    | Download-200-125-Exam-PDF    | Exam-Description-300-101-dumps    | Certs-300-101-date    | Hot-Sale-300-075-Exam    | Latest-exam-200-125-Dumps    | Exam-Description-200-125-dumps    | Latest-Updated-300-075-Exam    | hot-sale-book-210-260-book    | Dumps-200-901-exams-date    | Certs-200-901-date    | Latest-exam-1Z0-062-Dumps    | Hot-Sale-1Z0-062-Exam    | Certs-CSSLP-date    | 100%-Pass-70-383-Exams    | Latest-JN0-360-real-exam-questions    | 100%-Pass-4A0-100-Real-Exam-Questions    | Dumps-300-135-exams-date    | Passed-200-105-Tech-Exams    | Latest-Updated-200-310-Exam    | Download-300-070-Exam-PDF    | Hot-Sale-JN0-360-Exam    | 100%-Pass-JN0-360-Exams    | 100%-Pass-JN0-360-Real-Exam-Questions    | Dumps-JN0-360-exams-date    | Exam-Description-1Z0-876-dumps    | Latest-exam-1Z0-876-Dumps    | Dumps-HPE0-Y53-exams-date    | 2017-Latest-HPE0-Y53-Exam    | 100%-Pass-HPE0-Y53-Real-Exam-Questions    | Pass-4A0-100-Exam    | Latest-4A0-100-Questions    | Dumps-98-365-exams-date    | 2017-Latest-98-365-Exam    | 100%-Pass-VCS-254-Exams    | 2017-Latest-VCS-273-Exam    | Dumps-200-355-exams-date    | 2017-Latest-300-320-Exam    | Pass-300-101-Exam    | 100%-Pass-300-115-Exams    |
http://www.portvapes.co.uk/    | http://www.portvapes.co.uk/    |