GO语言工程实践课后作业:实现思路、代码以及路径记录 | 青训营

129 阅读2分钟

并发安全

在Go语言中,我们可以使用goroutine和channel来实现并发安全的操作。对于需要保证唯一性和并发安全的问题,我们可以使用sync包提供的锁机制来解决。下面是一个示例代码,用于支持发布帖子的操作,并保证帖子id的唯一性以及并发安全。

代码

package main 

import ( 
    "fmt" 
    "sync" 
) 

type Post struct { 
    ID int 
    Text string 
} 

type PostManager struct { 
    posts []Post 
    mutex sync.Mutex // 用于保护posts的互斥锁 
    index map[int]*Post 
} 

func NewPostManager() *PostManager { 
    pm := &PostManager{ 
        posts: make([]Post, 0), 
        index: make(map[int]*Post), 
    } 
    return pm 
} 

func (pm *PostManager) AddPost(id int, text string) bool { 
    pm.mutex.Lock() 
    defer pm.mutex.Unlock() 
    
    // 检查id是否已存在 
    if _, ok := pm.index[id]; ok { 
        return false 
    } 
    
    post := Post{ 
        ID: id, 
        Text: text, 
    } 
    
    // 添加到末尾 
    pm.posts = append(pm.posts, post) 
    // 更新索引 
    pm.index[id] = &pm.posts[len(pm.posts)-1] 
    
    return true 
} 

func main() { 
    pm := NewPostManager() 
    var wg sync.WaitGroup 
    
    // 并发添加帖子 
    for i := 1; i <= 10; i++ { 
        wg.Add(1) 
        go func(id int) { 
            defer wg.Done() 
            text := fmt.Sprintf("Post %d", id) 
            if pm.AddPost(id, text) { 
                fmt.Printf("Post %d added\n", id) 
            } else { 
                fmt.Printf("Post %d already exists\n", id) 
            } 
        }(i) 
    } 

    wg.Wait() 

    fmt.Printf("Total posts: %d\n", len(pm.posts)) 
}

实现思路

上述代码中,我们定义了两个结构体:Post表示帖子,包含帖子的ID和内容;PostManager表示帖子管理器,包含帖子列表(posts字段)、索引(index字段)和互斥锁(mutex字段)。

通过NewPostManager()函数,我们创建了一个帖子管理器实例。在AddPost()方法中,我们使用互斥锁保护了共享资源(postsindex),实现了并发安全。首先,我们检查帖子ID是否已存在于索引中,如果存在,则返回失败。如果不存在,则创建一个新的Post结构体,将其添加到posts末尾,并更新索引。最后,返回成功。

main()函数中,我们创建了一个帖子管理器实例pm,并使用sync.WaitGroup来等待所有goroutine的完成。然后,我们使用循环创建10个goroutine,并并发地向帖子管理器中添加帖子。每个goroutine负责添加一个帖子,其中帖子的ID从1到10递增。通过AddPost()方法,我们可以看到添加帖子的结果。

最后,我们输出帖子管理器中的帖子总数。

总结

通过上述代码,我们实现了发布帖子的操作,并解决了帖子ID的唯一性和索引的并发安全问题。在并发环境中,通过使用互斥锁来保护共享资源,可以确保操作的原子性,避免出现并发冲突。而使用sync.WaitGroup可以等待所有goroutine完成,确保所有操作都已完成。

这段代码展示了Go语言在并发编程方面的一些常用技巧和机制,对于理解并发安全和互斥锁的使用,以及如何解决并发环境下的共享资源问题,有一定的参考价值。