Atomic VS Mutex ?

Mar 26, 2010 at 9:01am

Atomic VS Mutex ?

Hello maxers,

What do you think it’s best to do :

*

if (ATOMIC_INCREMENT (&x->lock) == 1)
{
	do_something_time_consuming ( ) ;
	ATOMIC_DECREMENT (&x->lock) ;
}
else
{
	ATOMIC_DECREMENT (&x->lock) ;
}

*
*
*

if (!systhread_mutex_trylock (x->m_mutex))
{
	do_something_time_consuming ( ) ;
	systhread_mutex_unlock (x->m_mutex) ;
}

*

i know that’s a general question, but i need guru’s point of view ; specially about spinlock ; spinlock or not spinlock, that is the question !

Thanks.

#49363
Mar 26, 2010 at 6:01pm

well, the only difference is that, in the first case, there is no protection against other threads changing the state of your semaphore.

the various locking mechanisms (spinlocks, mutexes, semaphores…) exist because they solve different problems. without knowing what problem you’re trying to solve, it’s basically impossible to give any advice. only to say that, although i don’t have experience w/ using them in Max, some general advice would be to avoid spinlocks in favor of using the blocking systhread_mutex_lock.

i’m also a little alarmed that you’re putting “do something time consuming” inside your lock. generally speaking, you want any kind of lock to be as finely grained–to protect as small a chunk of code–as possible. are you sure your lock can’t go deeper inside do_something_time_consuming?

#177369
Mar 27, 2010 at 7:27am

Hello Brian,

to protect as small a chunk of code

that’s why i do investigations, because even if my code seems to work, i try to make it a little bit good-looking …

for example :

do_something (long n)
{
x->ptr = (long *)sysmem_newptr (sizeof(long) * n) ;
fill_and_make_nice_math_with_tab (x->ptr, n) ;
sysmem_freeptr (x->ptr) ;
}

can i go deeper ?

So i’m afraid about the inflence of my systhread_mutex_lock/unlock on the rest of max5 if do_something increase ; i thought just implement an i_am_busy_don’t_do_that stuff ; anyway i should go back into the thread chapter, there should be a thing which i understand not indeed,

Thanks .

#177370
Mar 27, 2010 at 4:04pm

why are you protecting this in the first place? it doesn’t look like it’s something where a race condition or deadlock with another thread can occur, as you’re obtaining and destroying your resources within the lock.

locks are about controlling access to shared resources among threads.

#177371
Mar 27, 2010 at 5:28pm

Hello Brian,

since i implement my own data structures (Factor Oracle & Hidden Markov Chains) i need to take care about that ; as clear/add/read messages send (very high speed only, but …) at the same time in timer and main thread crash my external without locking/mutex system.

#177372
Mar 27, 2010 at 6:29pm

ok, that sounds right. however, i’m now wondering why you’re using x->ptr to hold what seems from the code you posted to be an intermediate structure. why can’t its scope be specific to the function?

feel free to tell me that i simply don’t have the full picture.

#177373
Mar 28, 2010 at 7:25am

Hello Brian,

that was an example ; you don’t have the full picture ; on the other hand you lift an interesting point ; that’s true that i have few arrays that i can make specific, i do not know how it is going to act on the efficiency, but i am going to make the test … thank you very much.

#177374
Mar 28, 2010 at 9:34am

To go back to the original post I’d say it’s kind of dependent on what you are trying to achieve.

You are not actually spinlocking in either case as far as I can see – you’d need a loop to do that (repeatedly try the lock).

It doesn’t matter much if you do something expensive within your lock if you are not spinning on it (I don’t think) – or I suppose receiving a lot of calls to access the lock – I believe the first example you posted will be the fastest as the atomic operations are the basis on which mutexes etc. are built. In general the lighter your thread protection scheme the quicker they will execute. If you are going to spin on a lock you should be a lot more careful about how long you spend doing stuff within the lock.

Also, as long as you use your own mutex / semaphore then the only thing that will be affected is your own code. Avoid using global schemes like critical enter with the global region because they risk locking with other code.

@Brian Gruber – “well, the only difference is that, in the first case, there is no protection against other threads changing the state of your semaphore.”

I’m not sure I follow here – surely the code is correct, it’s just that the count can change, but only a thread incrementing from zero to one will gain the lock ?? I mean – I can see that the semaphore can change at any time during the lock, but that shouldn’t be an issue – right?

Alex

#177375
Mar 28, 2010 at 4:09pm

@Brian Gruber – “well, the only difference is that, in the first case, there is no protection against other threads changing the state of your semaphore.”

I’m not sure I follow here – surely the code is correct, it’s just that the count can change, but only a thread incrementing from zero to one will gain the lock ?? I mean – I can see that the semaphore can change at any time during the lock, but that shouldn’t be an issue – right?

It isn’t an issue so long as vanille sticks to her (his? her? sorry if i’m getting that wrong) semantics. The code is correct.

The difference is still there though. Some other thread can change the state of the semaphore (increment, decrement it, whatever). No other thread can release the mutex lock, and there is nothing else about it to be changed.

I’m not saying that’s necessarily bad; like you, i’m saying that without knowing the problem, i can’t really say which mechanism is best for solving it. So I merely pointed out the difference between the 2 presented mechanisms.

#177376
Mar 28, 2010 at 4:13pm

Hello maxers,

@Brian : oops, i can’t make it local ; because that’s finally not fun to deal with so many arrays and thousands of values in the stack …

Anyway :

@Alex : Thank you for these explanations which confirm of what I thought ; specially : “as long as you use your own mutex / semaphore then the only thing that will be affected is your own code” ; that i was not 100% sure.

The idea was to avoid spinlock (i wasn’t not 100% sure, too, about mutex way to lock, thanks for light), and make a “declutching” thing in case of extreme usage of my external. Of course, i am certainly the only one who will use it ;-) but all that kind of silly optimization help me to learn …

Edit : him !

Thanks both, and sorry for my approximate English …

#177377
Mar 28, 2010 at 4:33pm

@Vanille – no problem!

@Brain Gruber – yes – of course – good to be totally clear on things I agree – just checking there wasn’t anything I was missing! Yes – I guess my assumption is that the given code is the only code that accesses the variable, or that any other code is essentially the same. Obviously if it’s not all kinds of chaos is possible.

A.

#177378
Mar 31, 2011 at 5:26am

Great discussion, thanks for explanations!

#177379

You must be logged in to reply to this topic.