How to implement mutual exclusion(mutex)?

Good day, every process in my software is about to update 3 specific globals in row when the process is called to do some job. I need to guarantee that during updating of those globals with multiple processes there is only one process that is actually working with those globals. Moreover I need my globals unreadable if other process is in critical area.


Example:


(for example globals: ^data1, ^data2, ^data3 are critical area)

Should I use somehow function $LOCK() or there is another way how this can be done? I need only one process at the same time in critical area, due to that I don't need semaphores. And how to detect in other processes if there is some process already in critical area? Should I use transactions too if in the same time two processes would get into cirtical area where one of them should call trans. rollaback?


Thanks in advance for your answers and help.

Vote up!
Vote down!

Rating: 1

Comments: 5 Views: 107

Comments

To mark your question as "answered" on Developer Community,
please click the checkmark alongside the answer you (as author of the question) accept.

Vote up!
Vote down!

Rating: 0

3 answers

Answer

You have 2 Options for LOCK

1) LOCK lockargument  
either you succeed or you hang until you get success or forever

2) LOCK lockargument:timeout 

timeout releases your attempt after the defined time
and signal by system variable $TEST if you were successful or not

so your code may have this structure

LOCK  +(^a,^b,^c):0
If $TEST  {
    write "successful Locked",! 
}  ELSE  { write "attempt to Lock failed",! }

 

more on LOCK: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

if  failing you may want to identify your competitor using  ^$LOCK

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

Vote up!
Vote down!

Rating: 1

Robert, your first doc link is actually for $TEST. The link for LOCK is http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

Vote up!
Vote down!

Rating: 1

Answer

If I understand your problem correctly, then all you simply need to do, is lock all three specific globals at the beginning of each process, and unlock them once you're done. This will ensure that all three globals are being worked on by the same process. 

 

consider the two processes below:

Process1
 l +(^A,^B,^C):60 e  Process1
 s ^A 1 (($r(10)+1)*0.01)
 s ^B 1 (($r(10)+1)*0.01)
 s ^C 1 (($r(10)+1)*0.01)
 l -(^A,^B,^C)
 g Process1
 ;
 ;
 ;
Process2
 l +(^A,^B,^C):60 e  Process2
 s ^A 2 (($r(10)+1)*0.01)
 s ^B 2 (($r(10)+1)*0.01)
 s ^C 2 (($r(10)+1)*0.01)
 l -(^A,^B,^C)
 g Process2
 ;
 ;
 ;

 

Running these two process concurrently will still only result on all three ^A,^B,^C being worked on by the same process. 

 

Hope this helps. 

Ahmed 

Vote up!
Vote down!

Rating: 1

Thanks for answer. Of course. It seems I misunderstand it before. And I need lock without timing.

It is possible to catch somehow that second process found some critical area locked?. For example:
if (is not lock){
 lock

}else{

 behave else ( ..otherFunc())

}

Because if I use lock without timing, other process will sleep on lock like classical mutex, yes, your answer is correct, thanks, but I would like to know even more, if it is possible to externally check if lock is locked without falling asleep with process that will use LOCK +(^A,^B,^C), please?

Vote up!
Vote down!

Rating: 0

You can use a 0 second timeout on the LOCK command. That way your process will proceed immediately and you can check the value of $TEST (either directly, or indirectly using the ELSE command or an argumentless IF) to discover if you got the lock(s) or not.

Vote up!
Vote down!

Rating: 1

Ok, I understand now. Thanks

Vote up!
Vote down!

Rating: 0

Answer

Adding to the other answers, I notice the OP wrote "I need my globals unreadable if other process is in critical area".

This means you will need to obtain LOCKs before referencing (reading) the globals. But in this case you might opt to request shared LOCKs, e.g.

LOCK +(^A#"S",^B#"S",^C#"S")
WRITE !,"^A=",^A,!,"^B=",^B,!,"^C=",^C,!
LOCK -(^A#"S",^B#"S",^C#"S")

The use of shared locks will allow multiple concurrent reader processes, while still blocking all readers if a writer holds conflicting locks. A would-be writer will also be blocked while any readers still hold conflicting locks.

Vote up!
Vote down!

Rating: 2

Log in to answer