Last active
September 30, 2024 21:49
-
-
Save fancellu/3a59a38f4a5560074206d4294baecc33 to your computer and use it in GitHub Desktop.
Dining philosophers in golang (I have other impls in Rust, Scala, Scala+Cats effect here)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math/rand" | |
"sync" | |
"time" | |
"unsafe" | |
) | |
type Chopstick struct { | |
mutex sync.Mutex | |
} | |
type Philosopher struct { | |
name string | |
left *Chopstick | |
right *Chopstick | |
} | |
func (p *Philosopher) pickUpForks() { | |
// Choose the smaller ID fork first to avoid deadlock | |
if uintptr(unsafe.Pointer(&p.left.mutex)) < uintptr(unsafe.Pointer(&p.right.mutex)) { | |
p.left.mutex.Lock() | |
p.right.mutex.Lock() | |
} else { | |
p.right.mutex.Lock() | |
p.left.mutex.Lock() | |
} | |
fmt.Printf("%s is picking up forks\n", p.name) | |
} | |
func (p *Philosopher) eat() { | |
fmt.Println(p.name, "is eating") | |
sleepTime := time.Duration(rand.Intn(400)+400) * time.Millisecond | |
fmt.Printf("%s is sleeping for %v\n", p.name, sleepTime) | |
time.Sleep(sleepTime) | |
fmt.Println(p.name, "is done eating") | |
} | |
func (p *Philosopher) putDownForks() { | |
p.left.mutex.Unlock() | |
p.right.mutex.Unlock() | |
} | |
func dine(p *Philosopher, wg *sync.WaitGroup) { | |
defer wg.Done() | |
defer p.putDownForks() | |
p.pickUpForks() | |
p.eat() | |
} | |
func main() { | |
forkCount := 5 | |
forks := make([]*Chopstick, forkCount) | |
for i := range forks { | |
forks[i] = &Chopstick{} | |
} | |
philosophers := make([]*Philosopher, forkCount) | |
for i := range philosophers { | |
left := forks[i] | |
right := forks[(i+1)%forkCount] | |
philosophers[i] = &Philosopher{fmt.Sprintf("Philosopher %d", i), left, right} | |
} | |
var wg sync.WaitGroup | |
wg.Add(len(philosophers)) | |
for _, p := range philosophers { | |
go dine(p, &wg) | |
} | |
wg.Wait() | |
fmt.Println("All philosophers have eaten") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output
Philosopher 2 is picking up forks
Philosopher 2 is eating
Philosopher 0 is picking up forks
Philosopher 0 is eating
Philosopher 2 is sleeping for 442ms
Philosopher 0 is sleeping for 490ms
Philosopher 2 is done eating
Philosopher 3 is picking up forks
Philosopher 3 is eating
Philosopher 3 is sleeping for 783ms
Philosopher 0 is done eating
Philosopher 1 is picking up forks
Philosopher 1 is eating
Philosopher 1 is sleeping for 704ms
Philosopher 1 is done eating
Philosopher 3 is done eating
Philosopher 4 is picking up forks
Philosopher 4 is eating
Philosopher 4 is sleeping for 426ms
Philosopher 4 is done eating
All philosophers have eaten