Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
6
Task/Mutex/00-META.yaml
Normal file
6
Task/Mutex/00-META.yaml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
category:
|
||||
- Encyclopedia
|
||||
from: http://rosettacode.org/wiki/Mutex
|
||||
requires:
|
||||
- Concurrency
|
||||
23
Task/Mutex/00-TASK.txt
Normal file
23
Task/Mutex/00-TASK.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
A '''mutex''' (''abbreviated'' '''Mut'''ually '''Ex'''clusive access) 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.
|
||||
A [[task]] seizes (or acquires) the mutex, then accesses the resource, and after that releases the mutex.
|
||||
|
||||
A mutex is a low-level synchronization primitive exposed to deadlocking. A deadlock can occur with just two tasks and two mutexes (if each task attempts to acquire both mutexes, but in the opposite order).
|
||||
Entering the deadlock is usually aggravated by a [[race condition]] state, which leads to sporadic hangups, which are very difficult to track down.
|
||||
|
||||
=Variants of mutexes=
|
||||
|
||||
==Global and local mutexes==
|
||||
Usually the [[OS]] provides various implementations of mutexes corresponding to the variants of [[task]]s available in the OS. For example, system-wide mutexes can be used by [[process]]es. Local mutexes can be used only by [[threads]] etc. This distinction is maintained because, depending on the hardware, seizing a global mutex might be a thousand times slower than seizing a local one.
|
||||
|
||||
==Reentrant mutex==
|
||||
A reentrant mutex can be seized by the same [[task]] multiple times. Each seizing of the mutex is matched by releasing it, in order to allow another task to seize it.
|
||||
|
||||
==Read write mutex==
|
||||
A read write mutex can be seized at two levels for ''read'' and for ''write''. The mutex can be seized for ''read'' by any number of tasks. Only one task may seize it for '''write''. Read write mutexes are usually used to protect resources which can be accessed in mutable and immutable ways. Immutable (read) access is granted concurrently for many tasks because they do not change the resource state. Read write mutexes can be reentrant, global or local. Further, promotion operations may be provided. That's when a [[task]] that has seized the mutex for ''write'' releases it while keeping seized for ''read''. Note that the reverse operation is potentially deadlocking and requires some additional access policy control.
|
||||
|
||||
=Deadlock prevention=
|
||||
There exists a simple technique of deadlock prevention when mutexes are seized in some fixed order. This is discussed in depth in the [[Dining philosophers]] problem.
|
||||
|
||||
=Sample implementations / APIs=
|
||||
58
Task/Mutex/6502-Assembly/mutex.6502
Normal file
58
Task/Mutex/6502-Assembly/mutex.6502
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
;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
|
||||
2
Task/Mutex/8086-Assembly/mutex.8086
Normal file
2
Task/Mutex/8086-Assembly/mutex.8086
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
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]
|
||||
6
Task/Mutex/Ada/mutex-1.ada
Normal file
6
Task/Mutex/Ada/mutex-1.ada
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
protected type Mutex is
|
||||
entry Seize;
|
||||
procedure Release;
|
||||
private
|
||||
Owned : Boolean := False;
|
||||
end Mutex;
|
||||
10
Task/Mutex/Ada/mutex-2.ada
Normal file
10
Task/Mutex/Ada/mutex-2.ada
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
protected body Mutex is
|
||||
entry Seize when not Owned is
|
||||
begin
|
||||
Owned := True;
|
||||
end Seize;
|
||||
procedure Release is
|
||||
begin
|
||||
Owned := False;
|
||||
end Release;
|
||||
end Mutex;
|
||||
15
Task/Mutex/Ada/mutex-3.ada
Normal file
15
Task/Mutex/Ada/mutex-3.ada
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
declare
|
||||
M : Mutex;
|
||||
begin
|
||||
M.Seize; -- Wait infinitely for the mutex to be free
|
||||
... -- Critical code
|
||||
M.Release; -- Release the mutex
|
||||
...
|
||||
select
|
||||
M.Seize; -- Wait no longer than 0.5s
|
||||
or delay 0.5;
|
||||
raise Timed_Out;
|
||||
end select;
|
||||
... -- Critical code
|
||||
M.Release; -- Release the mutex
|
||||
end;
|
||||
13
Task/Mutex/BBC-BASIC/mutex.basic
Normal file
13
Task/Mutex/BBC-BASIC/mutex.basic
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
REM Create mutex:
|
||||
SYS "CreateMutex", 0, 0, 0 TO hMutex%
|
||||
|
||||
REM Wait to acquire mutex:
|
||||
REPEAT
|
||||
SYS "WaitForSingleObject", hMutex%, 1 TO res%
|
||||
UNTIL res% = 0
|
||||
|
||||
REM Release mutex:
|
||||
SYS "ReleaseMutex", hMutex%
|
||||
|
||||
REM Free mutex:
|
||||
SYS "CloseHandle", hMutex%
|
||||
1
Task/Mutex/C/mutex-1.c
Normal file
1
Task/Mutex/C/mutex-1.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
|
||||
1
Task/Mutex/C/mutex-2.c
Normal file
1
Task/Mutex/C/mutex-2.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
WaitForSingleObject(hMutex, INFINITE);
|
||||
1
Task/Mutex/C/mutex-3.c
Normal file
1
Task/Mutex/C/mutex-3.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
ReleaseMutex(hMutex);
|
||||
1
Task/Mutex/C/mutex-4.c
Normal file
1
Task/Mutex/C/mutex-4.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
CloseHandle(hMutex);
|
||||
3
Task/Mutex/C/mutex-5.c
Normal file
3
Task/Mutex/C/mutex-5.c
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#include <pthread.h>
|
||||
|
||||
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
2
Task/Mutex/C/mutex-6.c
Normal file
2
Task/Mutex/C/mutex-6.c
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pthread_mutex_t mutex;
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
1
Task/Mutex/C/mutex-7.c
Normal file
1
Task/Mutex/C/mutex-7.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
int error = pthread_mutex_lock(&mutex);
|
||||
1
Task/Mutex/C/mutex-8.c
Normal file
1
Task/Mutex/C/mutex-8.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
int error = pthread_mutex_unlock(&mutex);
|
||||
1
Task/Mutex/C/mutex-9.c
Normal file
1
Task/Mutex/C/mutex-9.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
int error = pthread_mutex_trylock(&mutex);
|
||||
11
Task/Mutex/D/mutex-1.d
Normal file
11
Task/Mutex/D/mutex-1.d
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
class Synced
|
||||
{
|
||||
public:
|
||||
synchronized int func (int input)
|
||||
{
|
||||
num += input;
|
||||
return num;
|
||||
}
|
||||
private:
|
||||
static num = 0;
|
||||
}
|
||||
46
Task/Mutex/D/mutex-2.d
Normal file
46
Task/Mutex/D/mutex-2.d
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import tango.core.Thread, tango.io.Stdout, tango.util.log.Trace;
|
||||
|
||||
class Synced {
|
||||
public synchronized int func (int input) {
|
||||
Trace.formatln("in {} at func enter: {}", input, foo);
|
||||
// stupid loop to consume some time
|
||||
int arg;
|
||||
for (int i = 0; i < 1000*input; ++i) {
|
||||
for (int j = 0; j < 10_000; ++j) arg += j;
|
||||
}
|
||||
foo += input;
|
||||
Trace.formatln("in {} at func exit: {}", input, foo);
|
||||
return arg;
|
||||
}
|
||||
private static int foo;
|
||||
}
|
||||
|
||||
void main(char[][] args) {
|
||||
SimpleThread[] ht;
|
||||
Stdout.print( "Starting application..." ).newline;
|
||||
|
||||
for (int i=0; i < 3; i++) {
|
||||
Stdout.print( "Starting thread for: " )(i).newline;
|
||||
ht ~= new SimpleThread(i+1);
|
||||
ht[i].start();
|
||||
}
|
||||
|
||||
// wait for all threads
|
||||
foreach( s; ht )
|
||||
s.join();
|
||||
}
|
||||
|
||||
class SimpleThread : Thread
|
||||
{
|
||||
private int d_id;
|
||||
this (int id) {
|
||||
super (&run);
|
||||
d_id = id;
|
||||
}
|
||||
|
||||
void run() {
|
||||
auto tested = new Synced;
|
||||
Trace.formatln ("in run() {}", d_id);
|
||||
tested.func(d_id);
|
||||
}
|
||||
}
|
||||
11
Task/Mutex/D/mutex-3.d
Normal file
11
Task/Mutex/D/mutex-3.d
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
class Synced {
|
||||
public int func (int input) {
|
||||
synchronized(Synced.classinfo) {
|
||||
// ...
|
||||
foo += input;
|
||||
// ...
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
private static int foo;
|
||||
}
|
||||
95
Task/Mutex/Delphi/mutex.delphi
Normal file
95
Task/Mutex/Delphi/mutex.delphi
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
unit main;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Winapi.Windows, System.SysUtils, System.Classes, Vcl.Controls, Vcl.Forms,
|
||||
System.SyncObjs, Vcl.StdCtrls;
|
||||
|
||||
type
|
||||
TForm1 = class(TForm)
|
||||
mmo1: TMemo;
|
||||
btn1: TButton;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure FormDestroy(Sender: TObject);
|
||||
procedure btn1Click(Sender: TObject);
|
||||
private
|
||||
{ Private declarations }
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
|
||||
var
|
||||
Form1: TForm1;
|
||||
FMutex: TMutex;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
procedure TForm1.FormCreate(Sender: TObject);
|
||||
begin
|
||||
FMutex := TMutex.Create();
|
||||
end;
|
||||
|
||||
procedure TForm1.FormDestroy(Sender: TObject);
|
||||
begin
|
||||
FMutex.Free;
|
||||
end;
|
||||
|
||||
// http://edgarpavao.com/2017/08/07/multithreading-e-processamento-paralelo-no-delphi-ppl/
|
||||
procedure TForm1.btn1Click(Sender: TObject);
|
||||
begin
|
||||
//Thread 1
|
||||
TThread.CreateAnonymousThread(
|
||||
procedure
|
||||
begin
|
||||
FMutex.Acquire;
|
||||
try
|
||||
TThread.Sleep(5000);
|
||||
TThread.Synchronize(TThread.CurrentThread,
|
||||
procedure
|
||||
begin
|
||||
mmo1.Lines.Add('Thread 1');
|
||||
end);
|
||||
finally
|
||||
FMutex.Release;
|
||||
end;
|
||||
end).Start;
|
||||
|
||||
//Thread 2
|
||||
TThread.CreateAnonymousThread(
|
||||
procedure
|
||||
begin
|
||||
FMutex.Acquire;
|
||||
try
|
||||
TThread.Sleep(1000);
|
||||
TThread.Synchronize(TThread.CurrentThread,
|
||||
procedure
|
||||
begin
|
||||
mmo1.Lines.Add('Thread 2');
|
||||
end);
|
||||
finally
|
||||
FMutex.Release;
|
||||
end;
|
||||
end).Start;
|
||||
|
||||
//Thread 3
|
||||
TThread.CreateAnonymousThread(
|
||||
procedure
|
||||
begin
|
||||
FMutex.Acquire;
|
||||
try
|
||||
TThread.Sleep(3000);
|
||||
TThread.Synchronize(TThread.CurrentThread,
|
||||
procedure
|
||||
begin
|
||||
mmo1.Lines.Add('Thread 3');
|
||||
end);
|
||||
finally
|
||||
FMutex.Release;
|
||||
end;
|
||||
end).Start;
|
||||
end;
|
||||
|
||||
end.
|
||||
16
Task/Mutex/E/mutex-1.e
Normal file
16
Task/Mutex/E/mutex-1.e
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
def makeMutex() {
|
||||
|
||||
# The mutex is available (released) if available is resolved, otherwise it
|
||||
# has been seized/locked. The specific value of available is irrelevant.
|
||||
var available := null
|
||||
|
||||
# The interface to the mutex is a function, taking a function (action)
|
||||
# to be executed.
|
||||
def mutex(action) {
|
||||
# By assigning available to our promise here, the mutex remains
|
||||
# unavailable to the /next/ caller until /this/ action has gotten
|
||||
# its turn /and/ resolved its returned value.
|
||||
available := Ref.whenResolved(available, fn _ { action <- () })
|
||||
}
|
||||
return mutex
|
||||
}
|
||||
39
Task/Mutex/E/mutex-2.e
Normal file
39
Task/Mutex/E/mutex-2.e
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
Creating the mutex:
|
||||
|
||||
? def mutex := makeMutex()
|
||||
# value: <mutex>
|
||||
|
||||
Creating the shared resource:
|
||||
|
||||
? var value := 0
|
||||
# value: 0
|
||||
|
||||
Manipulating the shared resource non-atomically so as to show a problem:
|
||||
|
||||
? for _ in 0..1 {
|
||||
> when (def v := (&value) <- get()) -> {
|
||||
> (&value) <- put(v + 1)
|
||||
> }
|
||||
> }
|
||||
|
||||
? value
|
||||
# value: 1
|
||||
|
||||
The value has been incremented twice, but non-atomically, and so is 1 rather
|
||||
than the intended 2.
|
||||
|
||||
? value := 0
|
||||
# value: 0
|
||||
|
||||
This time, we use the mutex to protect the action.
|
||||
|
||||
? for _ in 0..1 {
|
||||
> mutex(fn {
|
||||
> when (def v := (&value) <- get()) -> {
|
||||
> (&value) <- put(v + 1)
|
||||
> }
|
||||
> })
|
||||
> }
|
||||
|
||||
? value
|
||||
# value: 2
|
||||
40
Task/Mutex/Erlang/mutex.erl
Normal file
40
Task/Mutex/Erlang/mutex.erl
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
-module( mutex ).
|
||||
|
||||
-export( [task/0] ).
|
||||
|
||||
task() ->
|
||||
Mutex = erlang:spawn( fun() -> loop() end ),
|
||||
[erlang:spawn(fun() -> random:seed( X, 0, 0 ), print(Mutex, X, 3) end) || X <- lists:seq(1, 3)].
|
||||
|
||||
|
||||
|
||||
loop() ->
|
||||
receive
|
||||
{acquire, Pid} ->
|
||||
Pid ! {access, erlang:self()},
|
||||
receive
|
||||
{release, Pid} -> loop()
|
||||
end
|
||||
end.
|
||||
|
||||
mutex_acquire( Pid ) ->
|
||||
Pid ! {acquire, erlang:self()},
|
||||
receive
|
||||
{access, Pid} -> ok
|
||||
end.
|
||||
|
||||
mutex_release( Pid ) -> Pid ! {release, erlang:self()}.
|
||||
|
||||
print( _Mutex, _N, 0 ) -> ok;
|
||||
print( Mutex, N, M ) ->
|
||||
timer:sleep( random:uniform(100) ),
|
||||
mutex_acquire( Mutex ),
|
||||
io:fwrite( "Print ~p: ", [N] ),
|
||||
[print_slow(X) || X <- lists:seq(1, 3)],
|
||||
io:nl(),
|
||||
mutex_release( Mutex ),
|
||||
print( Mutex, N, M - 1 ).
|
||||
|
||||
print_slow( X ) ->
|
||||
io:fwrite( " ~p", [X] ),
|
||||
timer:sleep( 100 ).
|
||||
54
Task/Mutex/FreeBASIC/mutex.basic
Normal file
54
Task/Mutex/FreeBASIC/mutex.basic
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
' 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
|
||||
28
Task/Mutex/Go/mutex-1.go
Normal file
28
Task/Mutex/Go/mutex-1.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var value int
|
||||
var m sync.Mutex
|
||||
var wg sync.WaitGroup
|
||||
|
||||
func slowInc() {
|
||||
m.Lock()
|
||||
v := value
|
||||
time.Sleep(1e8)
|
||||
value = v+1
|
||||
m.Unlock()
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func main() {
|
||||
wg.Add(2)
|
||||
go slowInc()
|
||||
go slowInc()
|
||||
wg.Wait()
|
||||
fmt.Println(value)
|
||||
}
|
||||
40
Task/Mutex/Go/mutex-2.go
Normal file
40
Task/Mutex/Go/mutex-2.go
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
var value int
|
||||
|
||||
func slowInc(ch, done chan bool) {
|
||||
// channel receive, used here to implement mutex lock.
|
||||
// it will block until a value is available on the channel
|
||||
<-ch
|
||||
|
||||
// same as above
|
||||
v := value
|
||||
time.Sleep(1e8)
|
||||
value = v + 1
|
||||
|
||||
// channel send, equivalent to mutex unlock.
|
||||
// makes a value available on channel
|
||||
ch <- true
|
||||
|
||||
// channels can be used to signal completion too
|
||||
done <- true
|
||||
}
|
||||
|
||||
func main() {
|
||||
ch := make(chan bool, 1) // ch used as a mutex
|
||||
done := make(chan bool) // another channel used to signal completion
|
||||
go slowInc(ch, done)
|
||||
go slowInc(ch, done)
|
||||
// a freshly created sync.Mutex starts out unlocked, but a freshly created
|
||||
// channel is empty, which for us represents "locked." sending a value on
|
||||
// the channel puts the value up for grabs, thus representing "unlocked."
|
||||
ch <- true
|
||||
<-done
|
||||
<-done
|
||||
fmt.Println(value)
|
||||
}
|
||||
4
Task/Mutex/Haskell/mutex-1.hs
Normal file
4
Task/Mutex/Haskell/mutex-1.hs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
takeMVar :: MVar a -> IO a
|
||||
putMVar :: MVar a -> a -> IO ()
|
||||
tryTakeMVar :: MVar a -> IO (Maybe a)
|
||||
tryPutMVar :: MVar a -> a -> IO Bool
|
||||
7
Task/Mutex/Haskell/mutex-2.hs
Normal file
7
Task/Mutex/Haskell/mutex-2.hs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
x: = mutex() # create and return a mutex handle for sharing between threads needing to synchronize with each other
|
||||
|
||||
lock(x) # lock mutex x
|
||||
|
||||
trylock(x)) # non-blocking lock, succeeds only if there are no other thread already in the critical region
|
||||
|
||||
unlock(x) # unlock mutex x
|
||||
6
Task/Mutex/J/mutex.j
Normal file
6
Task/Mutex/J/mutex.j
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
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
|
||||
10
Task/Mutex/Java/mutex-1.java
Normal file
10
Task/Mutex/Java/mutex-1.java
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class VolatileClass{
|
||||
public Semaphore mutex = new Semaphore(1); //also a "fair" boolean may be passed which,
|
||||
//when true, queues requests for the lock
|
||||
public void needsToBeSynched(){
|
||||
//...
|
||||
}
|
||||
//delegate methods could be added for acquiring and releasing the mutex
|
||||
}
|
||||
10
Task/Mutex/Java/mutex-2.java
Normal file
10
Task/Mutex/Java/mutex-2.java
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
public class TestVolitileClass throws Exception{
|
||||
public static void main(String[] args){
|
||||
VolatileClass vc = new VolatileClass();
|
||||
vc.mutex.acquire(); //will wait automatically if another class has the mutex
|
||||
//can be interrupted similarly to a Thread
|
||||
//use acquireUninterruptibly() to avoid that
|
||||
vc.needsToBeSynched();
|
||||
vc.mutex.release();
|
||||
}
|
||||
}
|
||||
35
Task/Mutex/Java/mutex-3.java
Normal file
35
Task/Mutex/Java/mutex-3.java
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
public class Main {
|
||||
static Object mutex = new Object();
|
||||
static int i = 0;
|
||||
|
||||
public void addAndPrint()
|
||||
{
|
||||
System.out.print("" + i + " + 1 = ");
|
||||
i++;
|
||||
System.out.println("" + i);
|
||||
}
|
||||
|
||||
public void subAndPrint()
|
||||
{
|
||||
System.out.print("" + i + " - 1 = ");
|
||||
i--;
|
||||
System.out.println("" + i);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args){
|
||||
final Main m = new Main();
|
||||
new Thread() {
|
||||
public void run()
|
||||
{
|
||||
while (true) { synchronized(m.mutex) { m.addAndPrint(); } }
|
||||
}
|
||||
}.start();
|
||||
new Thread() {
|
||||
public void run()
|
||||
{
|
||||
while (true) { synchronized(m.mutex) { m.subAndPrint(); } }
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
1
Task/Mutex/Julia/mutex-1.julia
Normal file
1
Task/Mutex/Julia/mutex-1.julia
Normal file
|
|
@ -0,0 +1 @@
|
|||
SpinLock()
|
||||
1
Task/Mutex/Julia/mutex-2.julia
Normal file
1
Task/Mutex/Julia/mutex-2.julia
Normal file
|
|
@ -0,0 +1 @@
|
|||
lock(lock)
|
||||
1
Task/Mutex/Julia/mutex-3.julia
Normal file
1
Task/Mutex/Julia/mutex-3.julia
Normal file
|
|
@ -0,0 +1 @@
|
|||
unlock(lock)
|
||||
1
Task/Mutex/Julia/mutex-4.julia
Normal file
1
Task/Mutex/Julia/mutex-4.julia
Normal file
|
|
@ -0,0 +1 @@
|
|||
trylock(lock)
|
||||
1
Task/Mutex/Julia/mutex-5.julia
Normal file
1
Task/Mutex/Julia/mutex-5.julia
Normal file
|
|
@ -0,0 +1 @@
|
|||
islocked(lock)
|
||||
1
Task/Mutex/Julia/mutex-6.julia
Normal file
1
Task/Mutex/Julia/mutex-6.julia
Normal file
|
|
@ -0,0 +1 @@
|
|||
ReentrantLock()
|
||||
33
Task/Mutex/Logtalk/mutex.logtalk
Normal file
33
Task/Mutex/Logtalk/mutex.logtalk
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
:- object(slow_print).
|
||||
|
||||
:- threaded.
|
||||
|
||||
:- public(start/0).
|
||||
|
||||
:- private([slow_print_abc/0, slow_print_123/0]).
|
||||
:- synchronized([slow_print_abc/0, slow_print_123/0]).
|
||||
|
||||
start :-
|
||||
% launch two threads, running never ending goals
|
||||
threaded((
|
||||
repeat_abc,
|
||||
repeat_123
|
||||
)).
|
||||
|
||||
repeat_abc :-
|
||||
repeat, slow_print_abc, fail.
|
||||
|
||||
repeat_123 :-
|
||||
repeat, slow_print_123, fail.
|
||||
|
||||
slow_print_abc :-
|
||||
write(a), thread_sleep(0.2),
|
||||
write(b), thread_sleep(0.2),
|
||||
write(c), nl.
|
||||
|
||||
slow_print_123 :-
|
||||
write(1), thread_sleep(0.2),
|
||||
write(2), thread_sleep(0.2),
|
||||
write(3), nl.
|
||||
|
||||
:- end_object.
|
||||
55
Task/Mutex/M2000-Interpreter/mutex.m2000
Normal file
55
Task/Mutex/M2000-Interpreter/mutex.m2000
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
Form 80, 50
|
||||
Module CheckIt {
|
||||
Thread.Plan Concurrent
|
||||
Class mutex {
|
||||
mylock as boolean=True
|
||||
Function Lock {
|
||||
if not .mylock then exit
|
||||
.mylock<=False
|
||||
=True
|
||||
}
|
||||
Module Unlock {
|
||||
.mylock<=True
|
||||
}
|
||||
}
|
||||
Group PhoneBooth {
|
||||
NowUser$
|
||||
module UseIt (a$, x){
|
||||
.NowUser$<=a$
|
||||
Print a$+" phone home ",Int(x*100);"%"
|
||||
}
|
||||
module leave {
|
||||
.NowUser$<=""
|
||||
}
|
||||
}
|
||||
m=mutex()
|
||||
Flush
|
||||
Data "Bob", "John","Tom"
|
||||
For i=1 to 3 {
|
||||
Thread {
|
||||
\\ 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
|
||||
PhoneBooth.UseIt N$,C/Max
|
||||
iF C<Max Then Continue
|
||||
PhoneBooth.leave
|
||||
m.Unlock
|
||||
Thread This Erase
|
||||
} as K
|
||||
Read M$
|
||||
Thread K Execute Static N$=M$, C=0, Max=RANDOM(5,8)
|
||||
Thread K interval Random(300, 2000)
|
||||
}
|
||||
\\ Start we lock Phone Booth for service
|
||||
Service=m.lock()
|
||||
Main.Task 50 {
|
||||
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
|
||||
4
Task/Mutex/Nim/mutex-1.nim
Normal file
4
Task/Mutex/Nim/mutex-1.nim
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import locks
|
||||
|
||||
var mutex: Lock
|
||||
initLock mutex
|
||||
1
Task/Mutex/Nim/mutex-2.nim
Normal file
1
Task/Mutex/Nim/mutex-2.nim
Normal file
|
|
@ -0,0 +1 @@
|
|||
acquire mutex
|
||||
1
Task/Mutex/Nim/mutex-3.nim
Normal file
1
Task/Mutex/Nim/mutex-3.nim
Normal file
|
|
@ -0,0 +1 @@
|
|||
release mutex
|
||||
1
Task/Mutex/Nim/mutex-4.nim
Normal file
1
Task/Mutex/Nim/mutex-4.nim
Normal file
|
|
@ -0,0 +1 @@
|
|||
let success = tryAcquire mutex
|
||||
8
Task/Mutex/OCaml/mutex.ocaml
Normal file
8
Task/Mutex/OCaml/mutex.ocaml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
let m = Mutex.create() in
|
||||
Mutex.lock m; (* locks in blocking mode *)
|
||||
|
||||
if (Mutex.try_lock m)
|
||||
then ... (* did the lock *)
|
||||
else ... (* already locked, do not block *)
|
||||
|
||||
Mutex.unlock m;
|
||||
6
Task/Mutex/Objeck/mutex.objeck
Normal file
6
Task/Mutex/Objeck/mutex.objeck
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
m := ThreadMutex->New("lock a");
|
||||
# section locked
|
||||
critical(m) {
|
||||
...
|
||||
}
|
||||
# section unlocked
|
||||
11
Task/Mutex/Objective-C/mutex.m
Normal file
11
Task/Mutex/Objective-C/mutex.m
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
NSLock *m = [[NSLock alloc] init];
|
||||
|
||||
[m lock]; // locks in blocking mode
|
||||
|
||||
if ([m tryLock]) { // acquire a lock -- does not block if not acquired
|
||||
// lock acquired
|
||||
} else {
|
||||
// already locked, does not block
|
||||
}
|
||||
|
||||
[m unlock];
|
||||
13
Task/Mutex/Oforth/mutex.fth
Normal file
13
Task/Mutex/Oforth/mutex.fth
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import: parallel
|
||||
|
||||
: job(mut)
|
||||
mut receive drop
|
||||
"I get the mutex !" .
|
||||
2000 sleep
|
||||
"Now I release the mutex" println
|
||||
1 mut send drop ;
|
||||
|
||||
: mymutex
|
||||
| mut |
|
||||
Channel new dup send(1) drop ->mut
|
||||
10 #[ #[ mut job ] & ] times ;
|
||||
1
Task/Mutex/Oz/mutex-1.oz
Normal file
1
Task/Mutex/Oz/mutex-1.oz
Normal file
|
|
@ -0,0 +1 @@
|
|||
declare L = {Lock.new}
|
||||
3
Task/Mutex/Oz/mutex-2.oz
Normal file
3
Task/Mutex/Oz/mutex-2.oz
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
lock L then
|
||||
{System.show exclusive}
|
||||
end
|
||||
9
Task/Mutex/Oz/mutex-3.oz
Normal file
9
Task/Mutex/Oz/mutex-3.oz
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
class Test
|
||||
prop locking
|
||||
|
||||
meth test
|
||||
lock
|
||||
{Show exclusive}
|
||||
end
|
||||
end
|
||||
end
|
||||
28
Task/Mutex/Perl/mutex.pl
Normal file
28
Task/Mutex/Perl/mutex.pl
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
use Thread qw'async';
|
||||
use threads::shared;
|
||||
|
||||
my ($lock1, $lock2, $resource1, $resource2) :shared = (0) x 4;
|
||||
|
||||
sub use_resource {
|
||||
{ # curly provides lexical scope, exiting which causes lock to release
|
||||
lock $lock1;
|
||||
$resource1 --; # acquire resource
|
||||
sleep(int rand 3); # artifical delay to pretend real work
|
||||
$resource1 ++; # release resource
|
||||
print "In thread ", threads->tid(), ": ";
|
||||
print "Resource1 is $resource1\n";
|
||||
}
|
||||
{
|
||||
lock $lock2;
|
||||
$resource2 --;
|
||||
sleep(int rand 3);
|
||||
$resource2 ++;
|
||||
print "In thread ", threads->tid(), ": ";
|
||||
print "Resource2 is $resource2\n";
|
||||
}
|
||||
}
|
||||
|
||||
# create 9 threads and clean up each after they are done.
|
||||
for ( map async{ use_resource }, 1 .. 9) {
|
||||
$_->join
|
||||
}
|
||||
10
Task/Mutex/Phix/mutex-1.phix
Normal file
10
Task/Mutex/Phix/mutex-1.phix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
(notonline)-->
|
||||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (critical sections)</span>
|
||||
<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>
|
||||
<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>
|
||||
<!--
|
||||
18
Task/Mutex/Phix/mutex-2.phix
Normal file
18
Task/Mutex/Phix/mutex-2.phix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
(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>
|
||||
<!--
|
||||
1
Task/Mutex/Prolog/mutex-1.pro
Normal file
1
Task/Mutex/Prolog/mutex-1.pro
Normal file
|
|
@ -0,0 +1 @@
|
|||
mutex_create(Mutex, [alias(my_mutex)]).
|
||||
1
Task/Mutex/Prolog/mutex-2.pro
Normal file
1
Task/Mutex/Prolog/mutex-2.pro
Normal file
|
|
@ -0,0 +1 @@
|
|||
synchronized_goal(G) :- with_mutex(my_mutex, call(G)).
|
||||
5
Task/Mutex/PureBasic/mutex-1.basic
Normal file
5
Task/Mutex/PureBasic/mutex-1.basic
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
MyMutex=CreateMutex()
|
||||
Result = TryLockMutex(MyMutex)
|
||||
LockMutex(MyMutex)
|
||||
UnlockMutex(MyMutex)
|
||||
FreeMutex(MyMutex)
|
||||
34
Task/Mutex/PureBasic/mutex-2.basic
Normal file
34
Task/Mutex/PureBasic/mutex-2.basic
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
Declare ThreadedTask(*MyArgument)
|
||||
Define Mutex
|
||||
|
||||
If OpenConsole()
|
||||
Define thread1, thread2, thread3
|
||||
|
||||
Mutex = CreateMutex()
|
||||
thread1 = CreateThread(@ThreadedTask(), 1): Delay(5)
|
||||
thread2 = CreateThread(@ThreadedTask(), 2): Delay(5)
|
||||
thread3 = CreateThread(@ThreadedTask(), 3)
|
||||
WaitThread(thread1)
|
||||
WaitThread(thread2)
|
||||
WaitThread(thread3)
|
||||
|
||||
PrintN(#CRLF$+"Press ENTER to exit"): Input()
|
||||
FreeMutex(Mutex)
|
||||
CloseConsole()
|
||||
EndIf
|
||||
|
||||
Procedure ThreadedTask(*MyArgument)
|
||||
Shared Mutex
|
||||
Protected a, b
|
||||
For a = 1 To 3
|
||||
LockMutex(Mutex)
|
||||
; Without Lock-/UnLockMutex() here the output from the parallel threads would be all mixed.
|
||||
; Reading/Writing to shared memory resources are a common use for Mutextes i PureBasic
|
||||
PrintN("Thread "+Str(*MyArgument)+": Print 3 numbers in a row:")
|
||||
For b = 1 To 3
|
||||
Delay(75)
|
||||
PrintN("Thread "+Str(*MyArgument)+" : "+Str(b))
|
||||
Next
|
||||
UnlockMutex(Mutex)
|
||||
Next
|
||||
EndProcedure
|
||||
30
Task/Mutex/Python/mutex.py
Normal file
30
Task/Mutex/Python/mutex.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import threading
|
||||
from time import sleep
|
||||
|
||||
# res: max number of resources. If changed to 1, it functions
|
||||
# identically to a mutex/lock object
|
||||
res = 2
|
||||
sema = threading.Semaphore(res)
|
||||
|
||||
class res_thread(threading.Thread):
|
||||
def run(self):
|
||||
global res
|
||||
n = self.getName()
|
||||
for i in range(1, 4):
|
||||
# acquire a resource if available and work hard
|
||||
# for 2 seconds. if all res are occupied, block
|
||||
# and wait
|
||||
sema.acquire()
|
||||
res = res - 1
|
||||
print n, "+ res count", res
|
||||
sleep(2)
|
||||
|
||||
# after done with resource, return it to pool and flag so
|
||||
res = res + 1
|
||||
print n, "- res count", res
|
||||
sema.release()
|
||||
|
||||
# create 4 threads, each acquire resorce and work
|
||||
for i in range(1, 5):
|
||||
t = res_thread()
|
||||
t.start()
|
||||
6
Task/Mutex/Racket/mutex-1.rkt
Normal file
6
Task/Mutex/Racket/mutex-1.rkt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
(define foo
|
||||
(let ([sema (make-semaphore 1)])
|
||||
(lambda (x)
|
||||
(dynamic-wind (λ() (semaphore-wait sema))
|
||||
(λ() (... do something ...))
|
||||
(λ() (semaphore-post sema))))))
|
||||
10
Task/Mutex/Racket/mutex-2.rkt
Normal file
10
Task/Mutex/Racket/mutex-2.rkt
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
(define-syntax-rule (define/atomic (name arg ...) E ...)
|
||||
(define name
|
||||
(let ([sema (make-semaphore 1)])
|
||||
(lambda (arg ...)
|
||||
(dynamic-wind (λ() (semaphore-wait sema))
|
||||
(λ() E ...)
|
||||
(λ() (semaphore-post sema)))))))
|
||||
;; this does the same as the above now:
|
||||
(define/atomic (foo x)
|
||||
(... do something ...))
|
||||
3
Task/Mutex/Raku/mutex.raku
Normal file
3
Task/Mutex/Raku/mutex.raku
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
my $lock = Lock.new;
|
||||
|
||||
$lock.protect: { your-ad-here() }
|
||||
6
Task/Mutex/Ruby/mutex-1.rb
Normal file
6
Task/Mutex/Ruby/mutex-1.rb
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
require 'mutex_m'
|
||||
|
||||
class SomethingWithMutex
|
||||
include Mutex_m
|
||||
...
|
||||
end
|
||||
2
Task/Mutex/Ruby/mutex-2.rb
Normal file
2
Task/Mutex/Ruby/mutex-2.rb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
an_object = Object.new
|
||||
an_object.extend(Mutex_m)
|
||||
16
Task/Mutex/Ruby/mutex-3.rb
Normal file
16
Task/Mutex/Ruby/mutex-3.rb
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# acquire a lock -- block execution until it becomes free
|
||||
an_object.mu_lock
|
||||
|
||||
# acquire a lock -- return immediately even if not acquired
|
||||
got_lock = an_object.mu_try_lock
|
||||
|
||||
# have a lock?
|
||||
if an_object.mu_locked? then ...
|
||||
|
||||
# release the lock
|
||||
an_object.mu_unlock
|
||||
|
||||
# wrap a lock around a block of code -- block execution until it becomes free
|
||||
an_object.my_synchronize do
|
||||
do critical stuff
|
||||
end
|
||||
42
Task/Mutex/Rust/mutex.rust
Normal file
42
Task/Mutex/Rust/mutex.rust
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use std::{
|
||||
sync::{Arc, Mutex},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let shared = Arc::new(Mutex::new(String::new()));
|
||||
|
||||
let handle1 = {
|
||||
let value = shared.clone();
|
||||
thread::spawn(move || {
|
||||
for _ in 0..20 {
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
// The guard is valid until the end of the block
|
||||
let mut guard = value.lock().unwrap();
|
||||
guard.push_str("A");
|
||||
println!("{}", guard);
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
let handle2 = {
|
||||
let value = shared.clone();
|
||||
thread::spawn(move || {
|
||||
for _ in 0..20 {
|
||||
thread::sleep(Duration::from_millis(300));
|
||||
|
||||
{
|
||||
// Making the guard scope explicit here
|
||||
let mut guard = value.lock().unwrap();
|
||||
guard.push_str("B");
|
||||
println!("{}", guard);
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
handle1.join().ok();
|
||||
handle2.join().ok();
|
||||
shared.lock().ok().map_or((), |it| println!("Done: {}", it));
|
||||
}
|
||||
30
Task/Mutex/Shale/mutex.shale
Normal file
30
Task/Mutex/Shale/mutex.shale
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/local/bin/shale
|
||||
|
||||
thread library // POSIX threads, mutexes and semaphores
|
||||
time library // We use its sleep function here.
|
||||
|
||||
// The threead code which will lock the mutex, print a message,
|
||||
// then unlock the mutex.
|
||||
threadCode dup var {
|
||||
arg dup var swap =
|
||||
|
||||
stop lock thread::()
|
||||
arg "Thread %d has the mutex\n" printf
|
||||
stop unlock thread::()
|
||||
} =
|
||||
|
||||
stop mutex thread::() // Create the mutex.
|
||||
stop lock thread::() // Lock it until we've started the threads.
|
||||
|
||||
// Now create a few threads that will also try to lock the mutex.
|
||||
1 threadCode create thread::()
|
||||
2 threadCode create thread::()
|
||||
3 threadCode create thread::()
|
||||
4 threadCode create thread::()
|
||||
// The threads are all waiting to acquire the mutex.
|
||||
|
||||
"Main thread unlocking the mutex now..." println
|
||||
stop unlock thread::()
|
||||
|
||||
// Wait a bit to let the threads do their stuff.
|
||||
1000 sleep time::() // milliseconds
|
||||
13
Task/Mutex/Tcl/mutex-1.tcl
Normal file
13
Task/Mutex/Tcl/mutex-1.tcl
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
package require Thread
|
||||
|
||||
# How to create a mutex
|
||||
set m [thread::mutex create]
|
||||
|
||||
# This will block if the lock is already held unless the mutex is made recursive
|
||||
thread::mutex lock $m
|
||||
# Now locked...
|
||||
thread::mutex unlock $m
|
||||
# Unlocked again
|
||||
|
||||
# Dispose of the mutex
|
||||
thread::mutex destroy $m
|
||||
11
Task/Mutex/Tcl/mutex-2.tcl
Normal file
11
Task/Mutex/Tcl/mutex-2.tcl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
set rw [thread::rwmutex create]
|
||||
|
||||
# Get and drop a reader lock
|
||||
thread::rwmutex rlock $rw
|
||||
thread::rwmutex unlock $rw
|
||||
|
||||
# Get and drop a writer lock
|
||||
thread::rwmutex wlock $rw
|
||||
thread::rwmutex unlock $rw
|
||||
|
||||
thread::rwmutex destroy $rw
|
||||
14
Task/Mutex/Wren/mutex.wren
Normal file
14
Task/Mutex/Wren/mutex.wren
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
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
|
||||
2
Task/Mutex/Zkl/mutex-1.zkl
Normal file
2
Task/Mutex/Zkl/mutex-1.zkl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
var lock=Atomic.Lock(); lock.acquire(); doSomething(); lock.release();
|
||||
critical(lock){ doSomething(); }
|
||||
4
Task/Mutex/Zkl/mutex-2.zkl
Normal file
4
Task/Mutex/Zkl/mutex-2.zkl
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
var lock=Atomic.WriteLock();
|
||||
lock.acquireForReading(); doSomeReading(); lock.readerRelease();
|
||||
critical(lock,acquireForReading,readerRelease){ ... }
|
||||
lock.acquireForWriting(); write(); lock.writerRelease();
|
||||
Loading…
Add table
Add a link
Reference in a new issue