Skip to content

Instantly share code, notes, and snippets.

@fancellu
Last active September 30, 2024 21:49
Show Gist options
  • Save fancellu/3a59a38f4a5560074206d4294baecc33 to your computer and use it in GitHub Desktop.
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)
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")
}
@fancellu
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment