I have the following request queue:
type RequestQueue struct {
Requests []*http.Request
Mutex *sync.Mutex
}
func (rq *RequestQueue) Enqueue(req *http.Request) {
rq.Mutex.Lock()
defer rq.Mutex.Unlock()
rq.Requests = append(rq.Requests, req)
}
func (rq *queue) Dequeue() (*http.Request, error) {
rq.Mutex.Lock()
defer rq.Mutex.Unlock()
if len(rq.Requests) == 0 {
return nil, errors.New("dequeue: queue is empty")
}
req := rq.Requests[0]
rq.Requests = rq.Requests[1:]
return req, nil
}
Is it possible to do this with just the atomic package, without Mutex, type being simply type AtomicRequestQueue []*http.Request
, and will that bring any performance benefit?
CodePudding user response:
Use a channel, like chan *http.Request
. A channel is literally a FIFO queue.
What you call Enqueue
will just be a send operation c <- req
, and what you call Dequeue
will just be a receive operation req := <-c
.
Is it possible to do this with just the atomic package
You didn't state what is the real purpose of this thread-safe queue, however the use case you presented above seems to need synchronization, i.e. mutual exclusive access to the shared resource. The types in the atomic
package only guarantee that the result of the operation will be observed by other threads in a consistent fashion. There's no mutual exclusiveness involved.
If your queue needs more business logic than you are actually showing, a channel might be too primitive; in that case mutex locking might be your best bet. You may use sync.RWMutex
to reduce lock contention if you expect to have a lot of reads.