Mutex: Difference between revisions

14,063 bytes added ,  4 months ago
m
→‎{{header|Wren}}: Changed to Wren S/H
No edit summary
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(18 intermediate revisions by 9 users not shown)
Line 3:
[[Category:Encyclopedia]]
 
A '''mutex''' (''abbreviated''from "'''Mutmut'''uallyual '''Exex'''clusive accessclusion") is a synchronization object, a variant of [[semaphore]] with ''k''=1.
A mutex is said to be seized by a [[task]] decreasing ''k''.
It is released when the task restores ''k''. Mutexes are typically used to protect a shared resource from concurrent access.
Line 26:
 
=Sample implementations / APIs=
=={{header|6502 Assembly}}==
There isn't any hardware support for mutexes, but a simple flag in memory will do. This implementation is more akin to a "starting pistol" for some time-critical process such as the Nintendo Entertainment System's vBlank NMI (Non-Maskable Interrupt) which is typically used to update video memory. The function's parameters are pre-loaded in global memory, but the function that uses them won't be called unless the lock is released. Once all the parameters are ready, the main procedure can wait for the interrupt, after which it releases the lock and waits for the interrupt again. This time, the interrupt routine that needs those parameters is run, and when it's finished, the flag is locked again. For simplicity, most of the hardware-specific routines are omitted (and in reality would require additional mutexes since it usually takes more than one frame to do something like print a long string to the screen.)
 
''Side note: During a 6502's NMI, other interrupts cannot occur, not even another NMI. Therefore there is no chance that an IRQ will happen while executing NMI code.''
 
<syntaxhighlight lang="6502asm">;assume that the NES's screen is active and NMI occurs at the end of every frame.
 
mutex equ $01 ;these addresses in zero page memory will serve as the global variables.
vblankflag equ $02
 
main:
;if your time-sensitive function has parameters, pre-load them into global memory here.
;The only thing the NMI should have to do is write the data to the hardware registers.
 
jsr waitframe
LDA #$01 ;there's not enough time for a second vblank to occur between these two calls to waitframe().
STA mutex ;release the mutex. the next NMI will service the function we just unlocked.
jsr waitframe
 
halt:
jmp halt ;we're done - trap the cpu. NMI will still occur but nothing of interest happens since the mutex is locked.
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
nmi: ;every 1/60th of a second the CPU jumps here automatically.
pha
txa
pha
tya
pha ;pushAll
 
;for simplicity's sake the needs of the hardware are going to be omitted. A real NES game would perform sprite DMA here.
 
LDA mutex
BEQ exit_nmi
 
; whatever you wanted to gatekeep behind your mutex goes here.
; typically it would be something like a text box printer, etc.
; Something that needs to update the video RAM and do so ASAP.
 
LDA #$00
STA mutex ;lock the mutex again.
 
exit_nmi:
LDA #$01
STA vblankflag ;allow waitframe() to exit
 
pla
tay
pla
tax
pla ;popAll
rti
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
waitframe:
pha
LDA #0
sta vblankflag
.again:
LDA vblankflag
BEQ again ;this would loop infinitely if it weren't for vblankflag being set during NMI
pla
rts</syntaxhighlight>
 
=={{header|8086 Assembly}}==
<code>LOCK</code> is a prefix that can be added to instructions that read a value then write back to it, such as <code>INC</code> and <code>DEC</code>. This prefix "locks" the memory bus, preventing other CPUs (if any) from accessing the same memory location at the same time as the CPU executing the "locked" instruction. The lock lasts until the locked instruction is complete, at which point the lock is released. This isn't used much on the original 8086, and there are a few limitations to the usage of the <code>LOCK</code> prefix:
* You cannot <code>LOCK</code> registers (unless they are in brackets). This makes sense - each processor has its own registers and they can't access each others' registers anyway.
* <code>LOCK</code> can't be placed in front of any instruction on the 8086, only ones where it actually applies.
 
<syntaxhighlight lang="asm">lock inc word ptr [ds:TestData] ;increment the word at TestData. Only this CPU can access it right now.
lock dec byte ptr [es:di]</syntaxhighlight>
 
=={{header|Ada}}==
Line 31 ⟶ 102:
 
The mutex interface:
<langsyntaxhighlight lang="ada">protected type Mutex is
entry Seize;
procedure Release;
private
Owned : Boolean := False;
end Mutex;</langsyntaxhighlight>
The implementation of:
<langsyntaxhighlight lang="ada">protected body Mutex is
entry Seize when not Owned is
begin
Line 47 ⟶ 118:
Owned := False;
end Release;
end Mutex;</langsyntaxhighlight>
Here the entry Seize has a queue of the [[task]]s waiting for the mutex. The entry's barrier is closed when Owned is true. So any task calling to the entry will be queued. When the barrier is open the first task from the queue executes the entry and Owned becomes true closing the barrier again. The procedure Release simply sets Owned to false. Both Seize and Release are protected actions whose execution causes reevaluation of all barriers, in this case one of Seize.
 
Use:
<langsyntaxhighlight lang="ada">declare
M : Mutex;
begin
Line 65 ⟶ 136:
... -- Critical code
M.Release; -- Release the mutex
end;</langsyntaxhighlight>
It is also possible to implement mutex as a monitor task.
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> REM Create mutex:
SYS "CreateMutex", 0, 0, 0 TO hMutex%
Line 82 ⟶ 153:
REM Free mutex:
SYS "CloseHandle", hMutex%</langsyntaxhighlight>
 
=={{header|C}}==
Line 89 ⟶ 160:
{{works with|Win32}}
To create a mutex operating system "object":
<langsyntaxhighlight lang="c">HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);</langsyntaxhighlight>
To lock the mutex:
<syntaxhighlight lang ="c">WaitForSingleObject(hMutex, INFINITE);</langsyntaxhighlight>
To unlock the mutex
<syntaxhighlight lang ="c">ReleaseMutex(hMutex);</langsyntaxhighlight>
When the program is finished with the mutex:
<syntaxhighlight lang ="c">CloseHandle(hMutex);</langsyntaxhighlight>
 
===POSIX===
Line 102 ⟶ 173:
Creating a mutex:
 
<langsyntaxhighlight lang="c">#include <pthread.h>
 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;</langsyntaxhighlight>
 
Or:
 
<langsyntaxhighlight lang="c">pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);</langsyntaxhighlight>
 
Locking:
 
<langsyntaxhighlight lang="c">int error = pthread_mutex_lock(&mutex);</langsyntaxhighlight>
 
Unlocking:
 
<langsyntaxhighlight lang="c">int error = pthread_mutex_unlock(&mutex);</langsyntaxhighlight>
 
Trying to lock (but do not wait if it can't)
 
<langsyntaxhighlight lang="c">int error = pthread_mutex_trylock(&mutex);</langsyntaxhighlight>
 
=={{header|C++}}==
Line 134 ⟶ 205:
 
=={{header|D}}==
<syntaxhighlight lang="d">
<lang d>
class Synced
{
Line 146 ⟶ 217:
static num = 0;
}
</syntaxhighlight>
</lang>
 
Keep in mind that '''synchronized''' used as above works on a per-class-instance basis.
Line 152 ⟶ 223:
 
The following example tries to illustrate the problem:
<langsyntaxhighlight Dlang="d">import tango.core.Thread, tango.io.Stdout, tango.util.log.Trace;
 
class Synced {
Line 197 ⟶ 268:
tested.func(d_id);
}
}</langsyntaxhighlight>
 
Every created thread creates its own '''Synced''' object, and because the monitor created by synchronized statement is created for every object,
Line 205 ⟶ 276:
like here:
 
<syntaxhighlight lang="d">
<lang D>
class Synced {
public int func (int input) {
Line 217 ⟶ 288:
private static int foo;
}
</syntaxhighlight>
</lang>
=={{header|Delphi}}==
{{libheader| Winapi.Windows}}
Line 226 ⟶ 297:
{{libheader| System.SyncObjs}}
{{libheader| Vcl.StdCtrls}}
<syntaxhighlight lang="delphi">
<lang Delphi>
unit main;
 
Line 321 ⟶ 392:
end;
 
end.</langsyntaxhighlight>
{{out}}
<pre>Thread 1
Line 331 ⟶ 402:
E's approach to concurrency is to ''never'' block, in favor of message passing/event queues/callbacks. Therefore, it is unidiomatic to use a mutex at all, and incorrect, or rather ''unsafe'', to use a mutex which blocks the calling thread. That said, here is a mutex written in E.
 
<langsyntaxhighlight lang="e">def makeMutex() {
 
# The mutex is available (released) if available is resolved, otherwise it
Line 346 ⟶ 417:
}
return mutex
}</langsyntaxhighlight>
 
This implementation of a mutex is designed to have a very short implementation as well as usage in E. The mutex object is a function which takes a function ''action'' to be executed once the mutex is available. The mutex is unavailable until the return value of ''action'' resolves. This interface has been chosen over lock and unlock operations to reduce the hazard of unbalanced lock/unlock pairs, and because it naturally fits into E code.
Line 352 ⟶ 423:
Usage example:
 
<langsyntaxhighlight lang="e">Creating the mutex:
 
? def mutex := makeMutex()
Line 390 ⟶ 461:
 
? value
# value: 2</langsyntaxhighlight>
 
<code>when</code> blocks and <code>Ref.whenResolved</code> return a ''promise'' for the result of the deferred action, so the mutex here waits for the gratuitously complicated increment to complete before becoming available for the next action.
Line 396 ⟶ 467:
=={{header|Erlang}}==
Erlang has no mutexes so this is a super simple one, hand built to allow 3 slowly printing processes to print until done before the next one starts.
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( mutex ).
 
Line 437 ⟶ 508:
io:fwrite( " ~p", [X] ),
timer:sleep( 100 ).
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 451 ⟶ 522:
Print 3: 1 2 3
</pre>
 
 
=={{header|FreeBASIC}}==
Extracted from FreeBASIC help.
FreeBASIC has the following Mutex functions:
MutexCreate, MutexLock, MutexUnlock, MutexDestroy and ThreadCreate.
 
<syntaxhighlight lang="freebasic">' Threading synchronization using Mutexes
' If you comment out the lines containing "MutexLock" and "MutexUnlock", the
' threads will not be in sync and some of the data may be printed out of place.
 
Const max_hilos = 10
 
Dim Shared As Any Ptr bloqueo_tty
 
' Teletipo unfurls some text across the screen at a given location
Sub Teletipo(Byref texto As String, Byval x As Integer, Byval y As Integer)
'
' This MutexLock makes simultaneously running threads wait for each
' other, so only one at a time can continue and print output.
' Otherwise, their Locates would interfere, since there is only one cursor.
'
' It's impossible to predict the order in which threads will arrive here and
' which one will be the first to acquire the lock thus causing the rest to wait.
Mutexlock bloqueo_tty
For i As Integer = 0 To (Len(texto) - 1)
Locate x, y + i : Print Chr(texto[i])
Sleep 25, 1
Next i
' MutexUnlock releases the lock and lets other threads acquire it.
Mutexunlock bloqueo_tty
End Sub
 
Sub Hilo(Byval datos_usuario As Any Ptr)
Dim As Integer id = Cint(datos_usuario)
Teletipo "Hilo (" & id & ").........", 1 + id, 1
End Sub
 
' Create a mutex to syncronize the threads
bloqueo_tty = Mutexcreate()
 
' Create child threads
Dim As Any Ptr sucesos(0 To max_hilos - 1)
For i As Integer = 0 To max_hilos - 1
sucesos(i) = Threadcreate(@Hilo, Cptr(Any Ptr, i))
If sucesos(i) = 0 Then
Print "Error al crear el hilo:"; i
Exit For
End If
Next i
 
' This is the main thread. Now wait until all child threads have finished.
For i As Integer = 0 To max_hilos - 1
If sucesos(i) <> 0 Then Threadwait(sucesos(i))
Next i
 
' Clean up when finished
Mutexdestroy(bloqueo_tty)
Sleep</syntaxhighlight>
 
 
=={{header|Go}}==
Line 456 ⟶ 589:
{{trans|E}}
Go has mutexes, and here is an example use of a mutex, somewhat following the example of E. This code defines a slow incrementer, that reads a variable, then a significant amount of time later, writes an incremented value back to the variable. Two incrementers are started concurrently. Without the mutex, one would overwrite the other and the result would be 1. Using a mutex, as shown here, one waits for the other and the result is 2.
<langsyntaxhighlight lang="go">package main
 
import (
Line 483 ⟶ 616:
wg.Wait()
fmt.Println(value)
}</langsyntaxhighlight>
{{out}}
<pre>
Line 495 ⟶ 628:
As soon as things start getting complicated though, Go channels offer a much clearer alternative.
As a gateway from mutexes to channels, here is the above program implemented with channels:
<langsyntaxhighlight lang="go">package main
 
import (
Line 534 ⟶ 667:
<-done
fmt.Println(value)
}</langsyntaxhighlight>
The value passed on the channel is not accessed here, just as the internal state of a mutex is not accessed. Rather, it is only the effect of the value being available that is important. (Of course if you wanted to send something meaningful on the channel, a reference to the shared resource would be a good start...)
 
Line 540 ⟶ 673:
Haskell has a slight variation on the mutex, namely the MVar. MVars, unlike mutexes, are containers. However, they are similar enough that MVar () is essentially a mutex. A MVar can be in two states: empty or full, only storing a value when full. There are 4 main ways to deal with MVars:
 
<langsyntaxhighlight lang="haskell">takeMVar :: MVar a -> IO a
putMVar :: MVar a -> a -> IO ()
tryTakeMVar :: MVar a -> IO (Maybe a)
tryPutMVar :: MVar a -> a -> IO Bool
</syntaxhighlight>
</lang>
 
takeMVar will attempt to fetch a value from the MVar, and will block while the MVar is empty. After using this, the MVar will be left empty.
Line 555 ⟶ 688:
The following code uses features exclusive to Unicon.
 
<syntaxhighlight lang="unicon">
<lang Unicon>
 
x: = mutex() # create and return a mutex handle for sharing between threads needing to synchronize with each other
Line 565 ⟶ 698:
unlock(x) # unlock mutex x
 
</syntaxhighlight>
</lang>
 
=={{header|J}}==
 
J904 introduces mutexes.
 
Note: currently J mutexes do not have a meaningful display representation.
 
<syntaxhighlight lang="j"> name=. 10 T. 0 NB. create an exclusive mutex
name=. 10 T. 1 NB. create a shared (aka "recursive" or "reentrant") mutex
failed=. 11 T. mutex NB. take an exclusive lock on a mutex (waiting forever if necessary)
failed=. 11 T. mutex;seconds NB. try to take an exclusive lock on a mutex but may time out
NB. failed is 0 if lock was taken, 1 if lock was not taken
13 T. mutex NB. release lock on mutex</syntaxhighlight>
 
Recursive mutexes may be locked multiple times -- successive locks increase a counter. When unlocked as many times as previously locked, the mutex is released.
 
Exclusive mutexes will suspend (waiting "forever" if necessary) if the lock was already taken.
 
=={{header|Java}}==
Line 571 ⟶ 721:
 
Java 5 added a <code>Semaphore</code> class which can act as a mutex (as stated above, a mutex is "a variant of semaphore with ''k''=1").
<langsyntaxhighlight lang="java5">import java.util.concurrent.Semaphore;
 
public class VolatileClass{
Line 580 ⟶ 730:
}
//delegate methods could be added for acquiring and releasing the mutex
}</langsyntaxhighlight>
Using the mutex:
<langsyntaxhighlight lang="java5">public class TestVolitileClass throws Exception{
public static void main(String[] args){
VolatileClass vc = new VolatileClass();
Line 591 ⟶ 741:
vc.mutex.release();
}
}</langsyntaxhighlight>
 
Java also has the synchronized keyword, which allows almost any object to be used to enforce mutual exclusion.
 
<langsyntaxhighlight lang="java">public class Main {
static Object mutex = new Object();
static int i = 0;
Line 629 ⟶ 779:
}.start();
}
}</langsyntaxhighlight>
 
The "synchronized" keyword actually is a form of [[monitor]], which was a later-proposed solution to the same problems that mutexes and semaphores were designed to solve. More about synchronization may be found on Sun's website - http://java.sun.com/docs/books/tutorial/essential/concurrency/sync.html , and more about monitors may be found in any decent operating systems textbook.
Line 636 ⟶ 786:
From the Julia documentation:
 
<syntaxhighlight lang ="julia">SpinLock()</langsyntaxhighlight>
Create a non-reentrant lock. Recursive use will result in a deadlock. Each lock must be matched with an unlock.
 
<syntaxhighlight lang ="julia">lock(lock)</langsyntaxhighlight>
 
Acquire the lock when it becomes available. If the lock is already locked by a different task/thread, wait for it to become available.
Line 645 ⟶ 795:
Each lock must be matched by an unlock.
 
<syntaxhighlight lang ="julia">unlock(lock)</langsyntaxhighlight>
Releases ownership of the lock.
 
If this is a recursive lock which has been acquired before, decrement an internal counter and return immediately.
 
<syntaxhighlight lang ="julia">trylock(lock)</langsyntaxhighlight>
Acquire the lock if it is available, and return true if successful. If the lock is already locked by a different task/thread, return false.
 
Each successful trylock must be matched by an unlock.
 
<syntaxhighlight lang ="julia">islocked(lock)</langsyntaxhighlight>
Check whether the lock is held by any task/thread. This should not be used for synchronization (see instead trylock).
 
<syntaxhighlight lang ="julia">ReentrantLock()</langsyntaxhighlight>
Creates a re-entrant lock for synchronizing Tasks. The same task can acquire the lock as many times as required. Each lock must be matched with an unlock.
 
=={{header|Logtalk}}==
Logtalk provides a synchronized/0 directive for synchronizing all object (or category) predicates using the same implicit mutex and a synchronized/1 directive for synchronizing a set of predicates using the same implicit mutex. Follow an usage example of the synchronized/1 directive (inspired by the Erlang example). Works when using SWI-Prolog, XSB, or YAP as the backend compiler.
<langsyntaxhighlight lang="logtalk">
:- object(slow_print).
 
Line 697 ⟶ 847:
 
:- end_object.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 717 ⟶ 867:
Using concurrent (in interpreter level), after the execution of one statement, thread change. Using Sequential each thread block run all statements, until end, or leave some if a continue take place. In concurrent also a call to a module, or executing a block of code happen without in one thread.
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Form 80, 50
Module CheckIt {
Line 749 ⟶ 899:
\\ we use N$, C and Max as stack variables for each thread
\\ all other variables are shared for module
If C=0 Then if not m.lock() then Print N$+" waiting...................................":Refresh 20: Continue
C++
if c=1 then thread this interval 20
Line 765 ⟶ 915:
Service=m.lock()
Main.Task 50 {
\\ a block in a thread run alone
{
If Service Then if Keypress(32) then m.unlock: Service=false: Continue
If not Service then if Keypress(32) Then if m.lock() then Service=true : Continue
if PhoneBooth.NowUser$<>"" Then {
Print "Phone:";PhoneBooth.NowUser$: Refresh
} Else.if Service then Print "Service Time": Refresh
}
}
}
CheckIt
</syntaxhighlight>
</lang>
 
=={{header|Nim}}==
Line 783 ⟶ 930:
 
Creating a mutex:
<langsyntaxhighlight lang="nim">import locks
 
var mutex: Lock
initLock mutex</langsyntaxhighlight>
Locking:
<syntaxhighlight lang ="nim">acquire mutex</langsyntaxhighlight>
Unlocking:
<syntaxhighlight lang ="nim">release mutex</langsyntaxhighlight>
# Trying to lock (but do not wait if it can't)
<langsyntaxhighlight lang="nim">let success = tryAcquire mutex</langsyntaxhighlight>
 
=={{header|Objeck}}==
Objeck provides a simple way to lock a section of code. Please refer to the [[Objeck|programer's guide]] for addition information.
 
<langsyntaxhighlight lang="objeck">
m := ThreadMutex->New("lock a");
# section locked
Line 804 ⟶ 951:
}
# section unlocked
</syntaxhighlight>
</lang>
 
=={{header|Objective-C}}==
 
<langsyntaxhighlight lang="objc">NSLock *m = [[NSLock alloc] init];
 
[m lock]; // locks in blocking mode
Line 818 ⟶ 965:
}
[m unlock];</langsyntaxhighlight>
 
Reentrant mutex is provided by the <tt>NSRecursiveLock</tt> class.
Line 829 ⟶ 976:
It is very simple, there are four functions:
 
<langsyntaxhighlight lang="ocaml">let m = Mutex.create() in
Mutex.lock m; (* locks in blocking mode *)
 
Line 836 ⟶ 983:
else ... (* already locked, do not block *)
Mutex.unlock m;</langsyntaxhighlight>
 
=={{header|Oforth}}==
Line 845 ⟶ 992:
If the channel is empty, a task will wait until an object is available into the channel.
 
<langsyntaxhighlight Oforthlang="oforth">import: parallel
 
: job(mut)
Line 857 ⟶ 1,004:
| mut |
Channel new dup send(1) drop ->mut
10 #[ #[ mut job ] & ] times ;</langsyntaxhighlight>
 
=={{header|Oz}}==
Line 863 ⟶ 1,010:
 
Creating a mutex:
<langsyntaxhighlight lang="oz">declare L = {Lock.new}</langsyntaxhighlight>
 
The only way to acquire a mutex is to use the <code>lock</code> syntax. This ensures that releasing a lock can never be forgotten. Even if an exception occurs, the lock will be released.
<langsyntaxhighlight lang="oz">lock L then
{System.show exclusive}
end</langsyntaxhighlight>
 
To make it easier to work with objects, classes can be marked with the property <code>locking</code>. Instances of such classes have their own internal lock and can use a variant of the <code>lock</code> syntax:
<langsyntaxhighlight lang="oz">class Test
prop locking
 
Line 879 ⟶ 1,026:
end
end
end</langsyntaxhighlight>
 
=={{header|Perl}}==
Code demonstrating shared resources and simple locking. Resource1 and Resource2 represent some limited resources that must be exclusively used and released by each thread. Each thread reports how many of each is available; if it goes below zero, something is wrong. Try comment out either of the "lock $lock*" line to see what happens without locking.
<langsyntaxhighlight Perllang="perl">use Thread qw'async';
use threads::shared;
 
Line 910 ⟶ 1,057:
for ( map async{ use_resource }, 1 .. 9) {
$_->join
}</langsyntaxhighlight>
 
=={{header|Phix}}==
=== local mutexes ===
<lang Phix>integer cs = init_cs() -- Create a new critical section
Exclusive-only and non-reentrant.
enter_cs(cs) -- Begin mutually exclusive execution
<!--<syntaxhighlight lang="phix">(notonline)-->
bool b = try_cs(cs) -- As enter_cs, but yields false (0) if the lock cannot be obtained instantly
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (critical sections)</span>
leave_cs(cs) -- End mutually exclusive execution
<span style="color: #004080;">integer</span> <span style="color: #000000;">cs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">init_cs</span><span style="color: #0000FF;">()</span> <span style="color: #000080;font-style:italic;">-- Create a new critical section</span>
delete_cs(cs) -- Delete a critical section that you have no further use for</lang>
<span style="color: #0000FF;">...</span>
<span style="color: #7060A8;">enter_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cs</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- Begin mutually exclusive execution</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">try_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cs</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- As enter_cs, but yields false (0) if the lock cannot be obtained instantly</span>
<span style="color: #7060A8;">leave_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cs</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- End mutually exclusive execution</span>
<span style="color: #0000FF;">...</span>
<span style="color: #000000;">delete_cs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cs</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- Delete a critical section that you have no further use for</span>
<!--</syntaxhighlight>-->
=== global mutexes ===
Using file locking. Only shared locks are reentrant. Every call needs it's own bespoke retry logic. There is no builtin promotion operation.
<!--<syntaxhighlight lang="phix">(notonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (file i/o)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"log.txt"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"u"</span><span style="color: #0000FF;">),</span>
<span style="color: #0000FF;">...</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #000000;">lock_file</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">LOCK_SHARED</span><span style="color: #0000FF;">,{})</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">--while not lock_file(fn,LOCK_EXCLUSIVE,{}) do</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">></span><span style="color: #000000;">5</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- message/abort/retry/...</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #0000FF;">...</span>
<span style="color: #000000;">unlock_file</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,{})</span>
<span style="color: #0000FF;">...</span>
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
 
=={{header|PicoLisp}}==
Line 936 ⟶ 1,110:
 
To create a global mutex:
<langsyntaxhighlight lang="prolog">mutex_create(Mutex, [alias(my_mutex)]).</langsyntaxhighlight>
The recommended way to use the mutex is by wrapping code in a with_mutex/2 call, eg:
<langsyntaxhighlight Prologlang="prolog">synchronized_goal(G) :- with_mutex(my_mutex, call(G)).</langsyntaxhighlight>
This will wrap some code in a mutex to ensure exclusive access and release the mutex on completion (regardless or the result).
 
Line 946 ⟶ 1,120:
 
'''PureBasic has the following Mutex functions;'''
<langsyntaxhighlight PureBasiclang="purebasic">MyMutex=CreateMutex()
Result = TryLockMutex(MyMutex)
LockMutex(MyMutex)
UnlockMutex(MyMutex)
FreeMutex(MyMutex)</langsyntaxhighlight>
 
'''Example'''
<langsyntaxhighlight PureBasiclang="purebasic">Declare ThreadedTask(*MyArgument)
Define Mutex
 
Line 986 ⟶ 1,160:
UnlockMutex(Mutex)
Next
EndProcedure</langsyntaxhighlight>
 
=={{header|Python}}==
Line 994 ⟶ 1,168:
a semaphore grants access to a number of threads up to certain value.
 
<langsyntaxhighlight Pythonlang="python">import threading
from time import sleep
 
Line 1,023 ⟶ 1,197:
for i in range(1, 5):
t = res_thread()
t.start()</langsyntaxhighlight>
 
=={{header|Racket}}==
Line 1,029 ⟶ 1,203:
Racket has semaphores which can be used as mutexes in the usual way.
With other language features this can be used to implement new features -- for example, here is how we would implement a protected-by-a-mutex function:
<langsyntaxhighlight lang="racket">
(define foo
(let ([sema (make-semaphore 1)])
Line 1,035 ⟶ 1,209:
(dynamic-wind (λ() (semaphore-wait sema))
(λ() (... do something ...))
(λ() (semaphore-post sema))))))</langsyntaxhighlight>
and it is now easy to turn this into a macro for definitions of such functions:
<langsyntaxhighlight lang="racket">
(define-syntax-rule (define/atomic (name arg ...) E ...)
(define name
Line 1,047 ⟶ 1,221:
;; this does the same as the above now:
(define/atomic (foo x)
(... do something ...))</langsyntaxhighlight>
 
But more than just linguistic features, Racket has many additional synchronization tools in its VM.
Line 1,055 ⟶ 1,229:
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" perl6line>my $lock = Lock.new;
 
$lock.protect: { your-ad-here() }</langsyntaxhighlight>
Locks are reentrant. You may explicitly lock and unlock them, but the syntax above guarantees the lock will be unlocked on scope exit, even if by thrown exception or other exotic control flow. That being said, direct use of locks is discouraged in Perl 6Raku in favor of promises, channels, and supplies, which offer better composable semantics.
 
=={{header|Ruby}}==
Ruby's standard library includes a <tt>mutex_m</tt> module that can be mixed-in
to a class.
<langsyntaxhighlight lang="ruby">require 'mutex_m'
 
class SomethingWithMutex
include Mutex_m
...
end</langsyntaxhighlight>
 
Individual objects can be extended with the module too
<langsyntaxhighlight lang="ruby">an_object = Object.new
an_object.extend(Mutex_m)</langsyntaxhighlight>
 
An object with mutex powers can then:
<langsyntaxhighlight lang="ruby"># acquire a lock -- block execution until it becomes free
an_object.mu_lock
 
Line 1,090 ⟶ 1,264:
an_object.my_synchronize do
do critical stuff
end</langsyntaxhighlight>
 
=={{header|Rust}}==
Line 1,100 ⟶ 1,274:
append to a shared string.
 
<langsyntaxhighlight lang="rust">use std::{
sync::{Arc, Mutex},
thread,
Line 1,142 ⟶ 1,316:
shared.lock().ok().map_or((), |it| println!("Done: {}", it));
}
</syntaxhighlight>
</lang>
 
=={{header|Shale}}==
Shale includes a library that provides POSIX threads, semaphores and mutexes. Below is a really simple example usings threads and one mutex. There's a more complete example that includes semaphores available with the [https://github.com/sharkshead/shale Shale source code].
 
<langsyntaxhighlight Shalelang="shale">#!/usr/local/bin/shale
 
thread library // POSIX threads, mutexes and semaphores
Line 1,176 ⟶ 1,350:
 
// Wait a bit to let the threads do their stuff.
1000 sleep time::() // milliseconds</langsyntaxhighlight>
 
{{out}}
Line 1,188 ⟶ 1,362:
=={{header|Tcl}}==
Tcl's [http://tcl.cvs.sourceforge.net/*checkout*/tcl/thread/doc/html/thread.html#19 mutexes] have four functions.
<langsyntaxhighlight lang="tcl">package require Thread
 
# How to create a mutex
Line 1,200 ⟶ 1,374:
 
# Dispose of the mutex
thread::mutex destroy $m</langsyntaxhighlight>
There are also read-write mutexes available.
<langsyntaxhighlight lang="tcl">set rw [thread::rwmutex create]
 
# Get and drop a reader lock
Line 1,212 ⟶ 1,386:
thread::rwmutex unlock $rw
 
thread::rwmutex destroy $rw</langsyntaxhighlight>
 
=={{header|Wren}}==
As Wren's VM is effectively single threaded (only one fiber can run at a time), mutexes are only relevant for embedded scripts where two or more VMs are being run in parallel by the host and the VMs need shared access to some resource.
 
In such a case the host (see [https://github.com/wren-lang/wren/wiki/Language-Bindings here] for those currently available) would almost certainly deal directly with synchronization using whatever mechanisms were available to it and access to the resource would therefore be transparent as far as the Wren scripts were concerned.
 
However, to avoid excessive latency, a VM whose thread were continuing would need to signal to the host that it no longer needed the resource so the lock could be released thereby making it available to the other VM(s). Typically, a shared resource might need to be represented something like this in a Wren script:
 
<syntaxhighlight lang="wren">foreign class Resource {
// obtain a pointer to the resource when available
construct new() {}
 
// method for using the resource
foreign doSomething()
 
// signal to the host that the resource is no longer needed
foreign release()
}
 
var res = Resource.new() // wait for and obtain a lock on the resource
res.doSomething() // use it
res.release() // release the lock</syntaxhighlight>
 
=={{header|zkl}}==
zkl has two mutex objects, Lock (mutex) and WriteLock a mutex that allows multiple readers but only one writer.
The critical keyword fences code to ensure the lock is released when the code is done.
<langsyntaxhighlight lang="zkl">var lock=Atomic.Lock(); lock.acquire(); doSomething(); lock.release();
critical(lock){ doSomething(); }</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">var lock=Atomic.WriteLock();
lock.acquireForReading(); doSomeReading(); lock.readerRelease();
critical(lock,acquireForReading,readerRelease){ ... }
lock.acquireForWriting(); write(); lock.writerRelease();</langsyntaxhighlight>
 
{{omit from|TI-83 BASIC}} {{omit from|TI-89 BASIC}} <!-- Does not have user-defined data structures or objects. -->
9,476

edits