DEV Community

Discussion on: How to build a thread-safe Queue in Go?

Collapse
 
alirezaahmadi profile image
Alireza Ahmadi

Great writeup! Another, and maybe slightly simpler, way of implementing thread-safe queues in Go is to use Goroutines that are thread-safe by default:

type QueueGoRoutine struct {
    capacity int
    q        chan int
}

func (q *QueueGoRoutine) Insert(item int) error {
    if len(q.q) < int(q.capacity) {
        q.q <- item
        return nil
    }
    return errors.New("Queue is full")
}

func (q *QueueGoRoutine) Remove() (int, error) {
    if len(q.q) > 0 {
        item := <-q.q
        return item, nil
    }
    return 0, errors.New("Queue is empty")
}

func CreateQueueGoRoutine(capacity int) FifoQueue {
    return &QueueGoRoutine{
        capacity: capacity,
        q:        make(chan int, capacity),
    }
}
Enter fullscreen mode Exit fullscreen mode

In my simple benchmark on my device, this implementation has a slightly better performance too:

func BenchmarkQueueMutexInsert(b *testing.B) {
    q := CreateQueueMutex(b.N)

    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            q.Insert(1)
        }
    })
}

func BenchmarkQueueGoRoutineInsert(b *testing.B) {
    q := CreateQueueGoRoutine(b.N)

    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            q.Insert(1)
        }
    })
}

func BenchmarkQueueMutexRemove(b *testing.B) {
    q := CreateQueueMutex(b.N)
    for i := 0; i < b.N; i++ {
        q.Insert(1)
    }

    b.ResetTimer()

    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            q.Remove()
        }
    })
}

func BenchmarkQueueGoRoutineRemove(b *testing.B) {
    q := CreateQueueGoRoutine(b.N)
    for i := 0; i < b.N; i++ {
        q.Insert(1)
    }

    b.ResetTimer()

    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            q.Remove()
        }
    })
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
hvydya profile image
Harsha Vaidya

This is cool. I come from a Java background so channels weren't that intuitive for me. Thank you for taking the time to put the code. Super helpful.

Collapse
 
alirezaahmadi profile image
Alireza Ahmadi

Glad to help.