Question about Interlocked functions
-
1. Why Interlocked functions not have only-read operating funciton? 2.Interlocked function working at value A, at the same time other thread a function read value A, who first pass? If i want fist read operation then write operation, how to do? 3.example 1: more thread1 run, but i want only and only run first thread1 can do (1) until ReWork function run. Can those code good work?
volatile LONG g_bLock = FALSE; VOID thread1() { if (!g_bLock) { InterlockedExchange(&g_bLock, TRUE); // do something (1) } } VOID ReWork() { InterlockedExchange(&g_bLock, FALSE); }
Thanks. -
1. Why Interlocked functions not have only-read operating funciton? 2.Interlocked function working at value A, at the same time other thread a function read value A, who first pass? If i want fist read operation then write operation, how to do? 3.example 1: more thread1 run, but i want only and only run first thread1 can do (1) until ReWork function run. Can those code good work?
volatile LONG g_bLock = FALSE; VOID thread1() { if (!g_bLock) { InterlockedExchange(&g_bLock, TRUE); // do something (1) } } VOID ReWork() { InterlockedExchange(&g_bLock, FALSE); }
Thanks.1. Why Interlocked functions not have only-read operating funciton? This is almost meaningless to have such a function. Why? Because 1) Reading is itself not an issue of concurrent accesses (I mean if you only read, you will have no problems) 2) You still can simulate it by those interlocked functions. 2.Interlocked function working at value A, at the same time other thread a function read value A, who first pass? No one knows. This is impossible to state this or that thread will access the same resource first if they try it concurrently. If i want fist read operation then write operation, how to do? Then you have to use some synchronization between the reading and writting threads. Here would be appropriate the usage of Events. See here[^] for more details. 3.example 1: more thread1 run, but i want only and only run first thread1 can do (1) until ReWork function run. Can those code good work? Again a synchronization job. Refer to the article cited above.
-- ===== Arman
-
1. Why Interlocked functions not have only-read operating funciton? 2.Interlocked function working at value A, at the same time other thread a function read value A, who first pass? If i want fist read operation then write operation, how to do? 3.example 1: more thread1 run, but i want only and only run first thread1 can do (1) until ReWork function run. Can those code good work?
volatile LONG g_bLock = FALSE; VOID thread1() { if (!g_bLock) { InterlockedExchange(&g_bLock, TRUE); // do something (1) } } VOID ReWork() { InterlockedExchange(&g_bLock, FALSE); }
Thanks.If you want to use Interlocked*() to do locking then read about SpinLocks. A very simple version might look something like (note: doesn't suppport timeout, non-reentrant, doesn't enforce thread ownership, ...):
class SpinLock
{
volatile long lock;public:
SpinLock( void ) : lock(0) {;}void Aquire ( void ) { while( InterlockedCompareExchange(&lock, 1, 0) ) { SwitchToThread(); } } void Release ( void ) { lock = 0; }
};
...cmk Save the whales - collect the whole set
-
If you want to use Interlocked*() to do locking then read about SpinLocks. A very simple version might look something like (note: doesn't suppport timeout, non-reentrant, doesn't enforce thread ownership, ...):
class SpinLock
{
volatile long lock;public:
SpinLock( void ) : lock(0) {;}void Aquire ( void ) { while( InterlockedCompareExchange(&lock, 1, 0) ) { SwitchToThread(); } } void Release ( void ) { lock = 0; }
};
...cmk Save the whales - collect the whole set
-
void Release ( void ) { lock = 0; } why not use: InterlockedExchange(&lock, 0); I think that it's better. isn't?
HOW WHAT wrote:
void Release ( void ) { lock = 0; } why not use: InterlockedExchange(&lock, 0);
http://msdn2.microsoft.com/en-us/library/ms684122.aspx[^] Simple reads and writes to properly-aligned 32-bit variables are atomic operations. So, lock = 0; is atomic. InterlockedExchange will generate a full memory barrier http://msdn2.microsoft.com/en-us/library/12a04hfd(VS.80).aspx[^] A write to a volatile object (volatile write) has Release semantics ... This allows volatile objects to be used for memory locks and releases in multithreaded applications. For an explaination of full memory barrier and release semantics read: http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi/linux/bks/SGI_Developer/books/LX_DevDriver_PG/sgi_html/apa.html[^]
...cmk Save the whales - collect the whole set
-
HOW WHAT wrote:
void Release ( void ) { lock = 0; } why not use: InterlockedExchange(&lock, 0);
http://msdn2.microsoft.com/en-us/library/ms684122.aspx[^] Simple reads and writes to properly-aligned 32-bit variables are atomic operations. So, lock = 0; is atomic. InterlockedExchange will generate a full memory barrier http://msdn2.microsoft.com/en-us/library/12a04hfd(VS.80).aspx[^] A write to a volatile object (volatile write) has Release semantics ... This allows volatile objects to be used for memory locks and releases in multithreaded applications. For an explaination of full memory barrier and release semantics read: http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi/linux/bks/SGI_Developer/books/LX_DevDriver_PG/sgi_html/apa.html[^]
...cmk Save the whales - collect the whole set
Sorry, my bad englist... Umm, your meaning is if the code is a instruction, unneed use Interlocked functions? it unable happen some question? If "lock = 0" modification "if (0 == lock)", need Interlocked functions? and i want let nether code safe in multithreading, how to do? if (0 == lock) { lock = 1; } else { lock = 0; } Thanks very much for your answer.
-
HOW WHAT wrote:
void Release ( void ) { lock = 0; } why not use: InterlockedExchange(&lock, 0);
http://msdn2.microsoft.com/en-us/library/ms684122.aspx[^] Simple reads and writes to properly-aligned 32-bit variables are atomic operations. So, lock = 0; is atomic. InterlockedExchange will generate a full memory barrier http://msdn2.microsoft.com/en-us/library/12a04hfd(VS.80).aspx[^] A write to a volatile object (volatile write) has Release semantics ... This allows volatile objects to be used for memory locks and releases in multithreaded applications. For an explaination of full memory barrier and release semantics read: http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi/linux/bks/SGI_Developer/books/LX_DevDriver_PG/sgi_html/apa.html[^]
...cmk Save the whales - collect the whole set
-
http://msdn2.microsoft.com/en-us/library/ms684122.aspx[^][^] Unclear why those code run not happen error, if if "volatile bool Sentinel = true;" -> "bool Sentinel = true;" , have some different?
HOW WHAT wrote:
Unclear why those code run not happen error, if if "volatile bool Sentinel = true;" -> "bool Sentinel = true;" , have some different?
http://msdn2.microsoft.com/en-us/library/12a04hfd(VS.80).aspx[^] volatile is important. It tells the compiler that the value could change any time. e.g.
void Thread1( void )
{
while( Sentinal ) {
...
}
}
void Thread2( void )
{
...
Sentinal = false;
(wait for Thread1 to finish)
...
}If Sentinal is NOT volatile then Thread1 may cache the value of Sentinal when the Thread1 starts and never reload it becuase it is not used anywhere else in Thread1 (it optimizes the load out). In the example above this could cause Thread2 to wait forever becuase Thread1 never exits. If Sentinal IS volatile then Thread1 reloads the value in each iteration of the while loop. Therefore when Thread2 changes Sentinal Thread1 will see the change.
...cmk Save the whales - collect the whole set
-
Sorry, my bad englist... Umm, your meaning is if the code is a instruction, unneed use Interlocked functions? it unable happen some question? If "lock = 0" modification "if (0 == lock)", need Interlocked functions? and i want let nether code safe in multithreading, how to do? if (0 == lock) { lock = 1; } else { lock = 0; } Thanks very much for your answer.
Interlocked* is needed if you want to do 2 or more things with the value. In your example:
if( 0 == lock ) lock = 1;
else lock = 0;You are doing (at least) 2 things: 1. if( 0 == lock ) 2. lock = ...; Imagine 2 threads, Thread1 and Thread2. Start with lock = 0. Thread1 checks 1. above: if( 0 == lock ) and returns true Thread2 then checks 1. above: if( 0 == lock ) and returns true Thread1 then does 2. above: lock = 1 Thread2 then does 2. above: lock = 1 Problem: both threads think they are locked. You must use Interlocked* to make it like 1 instruction (i.e. atomic):
InterlockedCompareExchange(&lock, 1, 0)
...cmk Save the whales - collect the whole set
-
HOW WHAT wrote:
Unclear why those code run not happen error, if if "volatile bool Sentinel = true;" -> "bool Sentinel = true;" , have some different?
http://msdn2.microsoft.com/en-us/library/12a04hfd(VS.80).aspx[^] volatile is important. It tells the compiler that the value could change any time. e.g.
void Thread1( void )
{
while( Sentinal ) {
...
}
}
void Thread2( void )
{
...
Sentinal = false;
(wait for Thread1 to finish)
...
}If Sentinal is NOT volatile then Thread1 may cache the value of Sentinal when the Thread1 starts and never reload it becuase it is not used anywhere else in Thread1 (it optimizes the load out). In the example above this could cause Thread2 to wait forever becuase Thread1 never exits. If Sentinal IS volatile then Thread1 reloads the value in each iteration of the while loop. Therefore when Thread2 changes Sentinal Thread1 will see the change.
...cmk Save the whales - collect the whole set
-
Interlocked* is needed if you want to do 2 or more things with the value. In your example:
if( 0 == lock ) lock = 1;
else lock = 0;You are doing (at least) 2 things: 1. if( 0 == lock ) 2. lock = ...; Imagine 2 threads, Thread1 and Thread2. Start with lock = 0. Thread1 checks 1. above: if( 0 == lock ) and returns true Thread2 then checks 1. above: if( 0 == lock ) and returns true Thread1 then does 2. above: lock = 1 Thread2 then does 2. above: lock = 1 Problem: both threads think they are locked. You must use Interlocked* to make it like 1 instruction (i.e. atomic):
InterlockedCompareExchange(&lock, 1, 0)
...cmk Save the whales - collect the whole set
volatile bool Sentinel = true; unsigned ThreadFunc1( void* pArguments ) { while (Sentinel){;} ...... return 0; } unsigned ThreadFunc2( void* pArguments ) { Sentinel = false; // exit critical section return 0; }
-------------------------------------------- Ago, i think if a thread readning a address, and other thread write this address, that will be conflict. But why above not happen error and crash. you say "You are doing (at least) 2 things", but InterlockedExchange only 1 operation, how to use it. underside is my some code, can u help me see is it safe? 1.volatile LONG g_Value = -1; LONG Read() { ...... return InterlockedExchange(&g_Value, g_Value); } VOID Write(LONG NewValue) { ...... return InterlockedExchange(&g_Value, NewValue); } VOID Thread1() { if (Read >= 0) { Write(-1); for (INT i = 0; i < 10; i++) { Write(i); if (RunThread3() == error) { Write(-1); } } } } VOID Thread2() { // code same with Thread1 function }
----------------------------------------------------- 2.volatile LONG g_nIndex = -1; VOID Thread1() { InterlockedExchange(&g_nIndex, 1); } VOID Thread2() { do { } while (InterlockedExchange(&g_nIndex, g_nIndex) < -1); } VOID Thread3() { INT nIndex = GetIndex(); InterlockedExchange(&g_nIndex, nIndex); }
----------------------------------------------------- 3.volatile LONG g_nData1 = 0L; VOID Thread1() { if (InterlockedExchange(&g_nData1, g_nData1) == 0) { InterlockedExchangePointer(&g_nData1, 1); } ................. if (InterlockedExchangePointer(&g_nData1, g_nData1) == 1) { InterlockedExchangePointer(&g_nData1, 0L); } } VOID Thread2() { // code same with Thread1 }
------------------------------------------------------- 4.volatile LONG g_bIsLock = 0L; VOID Thread1() { if (InterlockedExchange(&g_bIsLock, g_bIsLock) == 1) { InterlockedExchange(&g_bIsLock, 0L); } else { InterlockedExchange(&g_bIsLock, 1); } } VOID Thread2() { InterlockedExchange(&g_bIsLock, g_bIsLock); } VOID Thread3() { if (InterlockedExchange(&g_bIsLock, g_bIsLock)) { } }
Thanks very much for your help. -
volatile bool Sentinel = true; unsigned ThreadFunc1( void* pArguments ) { while (Sentinel){;} ...... return 0; } unsigned ThreadFunc2( void* pArguments ) { Sentinel = false; // exit critical section return 0; }
-------------------------------------------- Ago, i think if a thread readning a address, and other thread write this address, that will be conflict. But why above not happen error and crash. you say "You are doing (at least) 2 things", but InterlockedExchange only 1 operation, how to use it. underside is my some code, can u help me see is it safe? 1.volatile LONG g_Value = -1; LONG Read() { ...... return InterlockedExchange(&g_Value, g_Value); } VOID Write(LONG NewValue) { ...... return InterlockedExchange(&g_Value, NewValue); } VOID Thread1() { if (Read >= 0) { Write(-1); for (INT i = 0; i < 10; i++) { Write(i); if (RunThread3() == error) { Write(-1); } } } } VOID Thread2() { // code same with Thread1 function }
----------------------------------------------------- 2.volatile LONG g_nIndex = -1; VOID Thread1() { InterlockedExchange(&g_nIndex, 1); } VOID Thread2() { do { } while (InterlockedExchange(&g_nIndex, g_nIndex) < -1); } VOID Thread3() { INT nIndex = GetIndex(); InterlockedExchange(&g_nIndex, nIndex); }
----------------------------------------------------- 3.volatile LONG g_nData1 = 0L; VOID Thread1() { if (InterlockedExchange(&g_nData1, g_nData1) == 0) { InterlockedExchangePointer(&g_nData1, 1); } ................. if (InterlockedExchangePointer(&g_nData1, g_nData1) == 1) { InterlockedExchangePointer(&g_nData1, 0L); } } VOID Thread2() { // code same with Thread1 }
------------------------------------------------------- 4.volatile LONG g_bIsLock = 0L; VOID Thread1() { if (InterlockedExchange(&g_bIsLock, g_bIsLock) == 1) { InterlockedExchange(&g_bIsLock, 0L); } else { InterlockedExchange(&g_bIsLock, 1); } } VOID Thread2() { InterlockedExchange(&g_bIsLock, g_bIsLock); } VOID Thread3() { if (InterlockedExchange(&g_bIsLock, g_bIsLock)) { } }
Thanks very much for your help.Your code does not make sense. Do not use: if( InterlockedExchange() ) { InterlockedExchange(); } This is bad, you are doing 2 things (test and set) in 2 instructions. Instead use: while( InterlockedCompareExchange(&lock, 1, 0) ) { // lock was == 0, now == 1, 'this' thread set lock = 1 } This is better, you are doing 2 things in 1 instruction.
...cmk Save the whales - collect the whole set
-
Your code does not make sense. Do not use: if( InterlockedExchange() ) { InterlockedExchange(); } This is bad, you are doing 2 things (test and set) in 2 instructions. Instead use: while( InterlockedCompareExchange(&lock, 1, 0) ) { // lock was == 0, now == 1, 'this' thread set lock = 1 } This is better, you are doing 2 things in 1 instruction.
...cmk Save the whales - collect the whole set
Yes, my code not make sense, it only write example for my question. Is nether code right now? Which Interlocked functions unneed? 1.
volatile LONG g_Value = -1; LONG Read() { // **return g_Value**; return InterlockedExchange(&g_Value, g_Value); } VOID Write(LONG NewValue) { // **g_Value = NewValue**; InterlockedExchange(&g_Value, NewValue); } VOID Thread1() { if (Read() >= 0) { Write(-1); for (INT i = 0; i < 10; i++) { ...... Write(i); if (RunThread2() == error) { ...... Write(-1); } } } } VOID Thread2() { // code same with Thread1 function }
----------------------------------------------------- 2.volatile LONG g_nIndex = -1; VOID Thread1() { // **g_nIndex = 1;** InterlockedExchange(&g_nIndex, 1); } VOID Thread2() { do { ...... } // **while (g_nIndex < -1);** while (InterlockedExchange(&g_nIndex, g_nIndex) < -1); } VOID Thread3() { INT nIndex = GetIndex(); // **g_nIndex = nIndex;** InterlockedExchange(&g_nIndex, nIndex); }
----------------------------------------------------- 3.volatile LONG g_nData1 = 0L; VOID Thread1() { // **if (0L == g_nData1) g_nData = 1;** InterlockedCompareExchange(g_nData1, 1, 0L); ................. // **if (1 == g_nData1) g_nData = 0L;** InterlockedCompareExchange(g_nData1, 0, 1); } VOID Thread2() { // code same with Thread1 }
------------------------------------------------------- 4.volatile LONG g_bIsLock = 0L; VOID Thread1() { // **if (1 == g_bIsLock) g_bIsLock = 0;** InterlockedCompareExchange(g_nData1, 0L, 1); } VOID Thread2() { // **if (0 == g_bIsLock)** if (InterlockedExchange(&g_bIsLock, g_bIsLock) == 0L) { ...... } } VOID Thread3() { // **if (1 == g_bIsLock)** if (InterlockedExchange(&g_bIsLock, g_bIsLock) == 1) { ...... } }
--------------------------------------------- And can u tell me why nether MSDN example unuseInterlocked functions, but it can work right and have not resource conflict( a thread read value, the other one write value)volatile bool Sentinel = true; unsigned ThreadFunc1( void* pArguments ) { while (Sentinel){;} ...... return 0; } unsigned ThreadFunc2( void* pArguments ) { Sentinel = false; // exit critical section return 0; }