zoukankan      html  css  js  c++  java
  • 《go语言程序设计》学习(九)

    一,线程安全的类

    package safeslice
    
    type safeSlice chan commandData
    
    type commandData struct {
        action  commandAction
        index   int
        item    interface{}
        result  chan<- interface{}
        data    chan<- []interface{}
        updater UpdateFunc
    }
    
    type commandAction int
    
    const (
        insert commandAction = iota
        remove
        at
        update
        end
        length
    )
    
    type UpdateFunc func(interface{}) interface{}
    
    type SafeSlice interface {
        Append(interface{})     // Append the given item to the slice
        At(int) interface{}     // Return the item at the given index position
        Close() []interface{}   // Close the channel and return the slice
        Delete(int)             // Delete the item at the given index position
        Len() int               // Return the number of items in the slice
        Update(int, UpdateFunc) // Update the item at the given index position
    }
    
    func New() SafeSlice {
        slice := make(safeSlice)
        go slice.run()
        return slice
    }
    
    func (slice safeSlice) run() {
        list := make([]interface{}, 0)
        for command := range slice {
            switch command.action {
            case insert:
                list = append(list, command.item)
            case remove: // potentially expensive for long lists
                if 0 <= command.index && command.index < len(list) {
                    list = append(list[:command.index],
                        list[command.index+1:]...)
                }
            case at:
                if 0 <= command.index && command.index < len(list) {
                    command.result <- list[command.index]
                } else {
                    command.result <- nil
                }
            case length:
                command.result <- len(list)
            case update:
                if 0 <= command.index && command.index < len(list) {
                    list[command.index] = command.updater(list[command.index])
                }
            case end:
                close(slice)
                command.data <- list
            }
        }
    }
    
    func (slice safeSlice) Append(item interface{}) {
        slice <- commandData{action: insert, item: item}
    }
    
    func (slice safeSlice) Delete(index int) {
        slice <- commandData{action: remove, index: index}
    }
    
    func (slice safeSlice) At(index int) interface{} {
        reply := make(chan interface{})
        slice <- commandData{at, index, nil, reply, nil, nil}
        return <-reply
    }
    
    func (slice safeSlice) Len() int {
        reply := make(chan interface{})
        slice <- commandData{action: length, result: reply}
        return (<-reply).(int)
    }
    
    // If the updater calls a safeSlice method we will get deadlock!
    func (slice safeSlice) Update(index int, updater UpdateFunc) {
        slice <- commandData{action: update, index: index, updater: updater}
    }
    
    func (slice safeSlice) Close() []interface{} {
        reply := make(chan []interface{})
        slice <- commandData{action: end, data: reply}
        return <-reply
    }

    这是一个线程安全的slice,表面上看,看不到任何锁或者互斥量等任何操作来实现线程安全。

    实际上,着应该说,说一个披着slice外衣的actor。。

    整个实现说这样:启动一个gorountin,并给它一个channel,当需要操作这个slice点时候,就把希望操作的信息封装进command这个struct内,然后把整个struct打包,从这个channel发送到gorountin,然后这个“slice”有序的从gorountin读取到这个command,就按照command的操作信息,把command操作执行。

    如果gorountin没有缓冲区,那么所有多操作都是阻塞的,也就是说,如果1-5这5个线程按顺序的都要操作这个slice,那么,在第一个请求执行完之前,其他线程的请求都时挂起的,直到第一个执行完,按顺序执行第二个。

  • 相关阅读:
    python3.5 安装mysqlclient
    python mysqlclient安装失败 Command "python setup.py egg_info" failed with error code 1
    python mysqlclient安装失败 Command "python setup.py egg_info" failed with error code 1
    JUC-多线程锁
    JUC-线程间通信
    JUC-LOCK接口
    JUC-JUC是什么?
    Zookeeper
    Mac 安装IDEA 2018.3 版本
    MyISAM和innoDB
  • 原文地址:https://www.cnblogs.com/mruoli/p/4709382.html
Copyright © 2011-2022 走看看