MST

星途 面试题库

面试题:Go中context在复杂缓存场景下的上下文关联优化

在一个具有读写锁控制的分布式缓存系统中,涉及多个并发的缓存读操作和偶尔的缓存写操作,如何使用context确保在缓存写操作进行时,新的读操作能快速感知并等待或取消?请描述具体设计思路及关键代码片段。
43.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 引入 context:在每个读操作和写操作中引入 context.Contextcontext 可以传递取消信号,用于控制读操作的生命周期。
  2. 写操作广播:当写操作开始时,通过一个广播机制通知所有正在进行或即将开始的读操作。
  3. 读操作监听:读操作在执行过程中监听 context 的取消信号。一旦收到取消信号,立即停止当前操作,等待或根据具体逻辑取消。

关键代码片段(以 Go 语言为例)

package main

import (
    "context"
    "fmt"
    "sync"
    "time"
)

// 模拟缓存数据
type Cache struct {
    data    map[string]string
    rwMutex sync.RWMutex
}

// 写操作
func (c *Cache) Write(ctx context.Context, key, value string) {
    c.rwMutex.Lock()
    defer c.rwMutex.Unlock()

    // 模拟写操作耗时
    select {
    case <-ctx.Done():
        fmt.Println("Write operation cancelled")
        return
    case <-time.After(2 * time.Second):
        c.data[key] = value
        fmt.Println("Write operation completed")
    }
}

// 读操作
func (c *Cache) Read(ctx context.Context, key string) (string, bool) {
    c.rwMutex.RLock()
    defer c.rwMutex.RUnlock()

    // 模拟读操作耗时
    select {
    case <-ctx.Done():
        fmt.Println("Read operation cancelled")
        return "", false
    case <-time.After(1 * time.Second):
        value, ok := c.data[key]
        return value, ok
    }
}

func main() {
    cache := Cache{data: make(map[string]string)}

    // 启动一个写操作
    ctx, cancel := context.WithCancel(context.Background())
    go func() {
        cache.Write(ctx, "key1", "value1")
    }()

    // 启动多个读操作
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            value, ok := cache.Read(ctx, "key1")
            if ok {
                fmt.Printf("Read value: %s\n", value)
            }
        }()
    }

    // 模拟写操作开始后,取消读操作
    time.Sleep(1 * time.Second)
    cancel()
    wg.Wait()
}

在上述代码中:

  1. Cache 结构体使用 sync.RWMutex 实现读写锁。
  2. Write 方法在写操作前加写锁,在操作过程中监听 context 的取消信号。
  3. Read 方法在读操作前加读锁,同样监听 context 的取消信号。
  4. main 函数中,启动一个写操作和多个读操作,通过 context 控制读操作在写操作开始后被取消。