首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在同一个执行线程中没有通道的上下文。

在同一个执行线程中没有通道的上下文。
EN

Stack Overflow用户
提问于 2020-06-06 03:44:55
回答 1查看 435关注 0票数 1

如果通过上下文语义在同一个执行线程中花费大量时间计算,我就不能弄清楚如何取消一个任务?

我使用这个例子作为一个参考点test.go

这里的目标是调用一个doWork,如果doWork花费了很长时间来计算,那么GetValueWithDeadline应该在超时后返回0,或者如果调用方调用cancel取消等待(这里主要是调用者)或返回在给定时间窗口中返回的值。

同样的场景可以用不同的方式来完成。(单独的goroutine睡眠,唤醒检查值等,互斥对象上的条件等等)但我真的想了解使用上下文的正确方法。

我理解的通道语义,但在这里我无法达到预期的效果,默认情况调用默认情况下的doWork错误和睡眠。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
    "context"
    "fmt"
    "log"
    "math/rand"
    "sync"
    "time"
)

type Server struct {
    lock sync.Mutex
}

func NewServer() *Server {
    s := new(Server)
    return s
}

func (s *Server) doWork() int {
    s.lock.Lock()
    defer s.lock.Unlock()
    r := rand.Intn(100)
    log.Printf("Going to nap for %d", r)
    time.Sleep(time.Duration(r) * time.Millisecond)
    return r
}

// I take an example from here and it very unclear where is do work executed
// https://golang.org/src/context/context_test.go

func (s *Server)  GetValueWithDeadline(ctx context.Context) int {
    val := 0
    select {
        case <- time.After(150 * time.Millisecond):
                fmt.Println("overslept")
                return 0
        case <- ctx.Done():
                fmt.Println(ctx.Err())
                return 0
        default:
                val = s.doWork()
    }

    return all
}

func main() {

    rand.Seed(time.Now().UTC().UnixNano())
    s := NewServer()
    for i :=0; i < 10; i++ {
        d := time.Now().Add(50 * time.Millisecond)
        ctx, cancel := context.WithDeadline(context.Background(), d)
        log.Print(s.GetValueWithDeadline(ctx))
        cancel()
    }
}

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-06 05:34:37

您的方法存在多个问题。

问题上下文解决了什么?

首先,在Go中发明上下文的主要原因是它们允许统一一种取消一组任务的方法。

要使用一个简单的例子来解释这个概念,请考虑向某个服务器发送一个客户端请求;为了进一步简化,让它成为一个HTTP请求。客户端连接到服务器,发送一些数据告诉服务器如何完成请求,然后等待服务器响应。

现在让我们假设请求需要在服务器上进行精细且耗时的处理--例如,假设它需要对多个远程数据库引擎执行多个复杂的查询,对外部服务执行多个HTTP请求,然后处理所获得的结果以实际生成客户端想要的数据。

因此,客户端启动其请求,服务器继续处理所有这些请求。

为了隐藏服务器为完成请求而必须执行的单个任务的延迟,它在单独的goroutines中运行这些任务。一旦每个goroutine完成指定的任务,它就会将其结果(和/或错误)传递回处理客户端请求的goroutine,等等。

现在假设客户机由于任何原因不能等待对其请求的响应--网络中断、客户端软件中的显式超时、用户杀死发起请求的应用程序等等--有很多可能性。

正如您所看到的,服务器继续花费资源来完成逻辑上绑定到“现在死亡”请求的任务是没有什么意义的:无论如何,没有人能听到结果。

因此,一旦我们知道请求不会完成,就应该收获这些任务,而这正是上下文发挥作用的地方:您可以将每个传入的请求与单个上下文关联起来,然后将其传递给为完成请求而产生的任何goroutine,或者从请求中派生出另一个请求,并将其传递给它。然后,一旦您取消了“根”请求,该信号就会传播到从根请求派生的整个请求树中。

现在,每个被赋予上下文的goroutine,可能会在发送取消信号时“监听”通知它,并且一旦goroutine注意到它可能会放下它正在忙着做的任何事情并退出。

就实际的context.Context类型而言,这个信号被称为“完成”--就像“我们完成了与上下文相关的任何事情”--这就是为什么希望知道它应该停止工作的goroutine在上下文的方法Done返回的一个特殊通道上监听。

回到你的例子

为了让它发挥作用,你应该做一些如下的事情:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func (s *Server) doWork(ctx context.Context) int {
    s.lock.Lock()
    defer s.lock.Unlock()

    r := rand.Intn(100)
    log.Printf("Going to nap for %d", r)
    select {
    case <- time.After(time.Duration(r) * time.Millisecond):
        return r
    case <- ctx.Done():
        return -1
    }
}

func (s *Server)  GetValueWithTimeout(ctx context.Context, maxTime time.Duration) int {
    d := time.Now().Add(maxTime)
    ctx, cancel := context.WithDeadline(ctx, d)
    defer cancel()

    return s.doWork(ctx)
}

func main() {
    const maxTime = 50 * time.Millisecond

    rand.Seed(time.Now().UTC().UnixNano())

    s := NewServer()
    for i :=0; i < 10; i++ {
        v := s.GetValueWithTimeout(context.Background(), maxTime)
        log.Print(v)
    }
}

(游乐场)。

那么这里发生了什么?

GetValueWithTimeout方法接受它应该使用的doWork方法产生值的最大时间,计算截止日期,导出一个上下文,该上下文在截止日期从传递给该方法的上下文传递后取消,并使用新的context对象调用doWork

doWork方法启动自己的计时器,使其在随机时间间隔后消失,然后侦听上下文和计时器。

这是一个关键点:执行某些工作单元的代码应该是可取消的,它必须检查上下文才能自动“完成”。

因此,在我们的玩具示例中,要么是doWork自己的计时器首先触发,要么是首先到达生成上下文的截止日期;无论首先发生什么,都会使select语句解除阻塞并继续进行。

请注意,如果您的“做工作”代码更复杂--它实际上会做一些事情而不是睡觉--您很可能需要定期检查上下文的状态,通常是在执行该工作的不生动的部分之后。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62231235

复制
相关文章
iOS开发中在指定的某些线程执行完之后去执行其他线程
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/79139208
用户1451823
2018/09/13
1.2K0
iOS开发中在指定的某些线程执行完之后去执行其他线程
如何让Task在非线程池线程中执行?
Task承载的操作需要被调度才能被执行,由于.NET默认采用基于线程池的调度器,所以Task默认在线程池线程中执行。但是有的操作并不适合使用线程池,比如我们在一个ASP.NET Core应用中承载了一些需要长时间执行的后台操作,由于线程池被用来处理HTTP请求,如果这些后台操作也使用线程池来调度,就会造成相互影响。在这种情况下,使用独立的一个或者多个线程来执行这些后台操作可能是一个更好的选择。
蒋金楠
2023/05/31
8010
如何让Task在非线程池线程中执行?
理解JavaScript 中的执行上下文和执行栈
执行栈,也叫调用栈,具有 LIFO(后进先出)结构,用于存储在代码执行期间创建的所有执行上下文。
挨踢小子部落阁
2023/03/16
4090
理解JavaScript 中的执行上下文和执行栈
理解JavaScript 中的执行上下文和执行栈
变量提升的原因:在创建阶段,函数声明存储在环境中,而变量会被设置为undefined(在 var 的情况下)或保持未初始化(在 let 和 const 的情况下)。所以这就是为什么可以在声明之前访问 var 定义的变量(尽管是 undefined),但如果在声明之前访问 let 和 const 定义的变量就会提示引用错误的原因。这就是所谓的变量提升。 执行阶段 此阶段,完成对所有变量的分配,最后执行代码。 如果 Javascript 引擎在源代码中声明的实际位置找不到 let 变量的值,那么将为其分配 undefined 值。
用户7657330
2020/08/16
6330
Celery 4.3.0 在task中执行多线程任务
在开发的调试过程中,发现如果在django项目里面或者celery的task中使用协程gevent的话,使用monkey补丁的时候会报错。
Devops海洋的渔夫
2019/09/24
2.5K0
Celery 4.3.0 在task中执行多线程任务
JavaScript中的执行上下文和堆栈[每日前端夜话(0x0C)]
在这篇文章中,我将深入探讨JavaScript的最基本部分之一,即Execution Context(执行上下文)。 在本文结束时,你应该对解释器了解得更清楚:为什么在声明它们之前可以使用某些函数或变量?以及它们的值是如何确定的?
疯狂的技术宅
2019/03/27
1.2K0
JavaScript中的执行上下文和堆栈[每日前端夜话(0x0C)]
从执行上下文角度重新理解.NET(Core)的多线程编程[3]:安全上下文
在前两篇文章(《基于调用链的”参数”传递》和《同步上下文》)中,我们先后介绍了CallContext(IllogicalCallContext和LogicalCallContext)、AsyncLocal<T>和SynchronizationContext,它们都是线程执行上下文的一部分。本篇介绍的安全上下文(SecurityContext)同样是执行上下文的一部分,它携带了的身份和权限相关的信息决定了执行代码拥有的控制权限。
蒋金楠
2020/12/01
5730
从执行上下文角度重新理解.NET(Core)的多线程编程[3]:安全上下文
从执行上下文角度重新理解.NET(Core)的多线程编程[2]:同步上下文
一般情况下,我们可以将某项操作分发给任意线程来执行,但有的操作确实对于执行的线程是有要求的,最为典型的场景就是:GUI针对UI元素的操作必须在UI主线程中执行。将指定的操作分发给指定线程进行执行的需求可以通过同步上下文(SynchronizationContext)来实现。你可能从来没有使用过SynchronizationContext,但是在基于Task的异步编程中,它却总是默默存在。今天我们就来认识一下这个SynchronizationContext对象。
蒋金楠
2020/11/26
1.1K0
从执行上下文角度重新理解.NET(Core)的多线程编程[2]:同步上下文
BackgroundWorker在单独的线程上执行操作
直接使用多线程有时候会带来莫名其妙的错误,不定时的发生,有时候会让程序直接崩溃,其实BackgroundWorker 类允许您在单独的专用线程上运行操作。可以通过编程方式创建 BackgroundWorker,也可以将它从“工具箱”的“组件”选项卡中拖到窗体上。如果在 Windows 窗体设计器中创建 BackgroundWorker,则它会出现在组件栏中,而且它的属性会显示在“属性”窗口中。
张果
2022/05/09
1.2K0
BackgroundWorker在单独的线程上执行操作
执行上下文
执行上下文为我们的可执行代码块提供了执行前的必要准备工作,如变量对象的定义、作用域链的扩展、提供调用者的对象引用等信息。
用户3258338
2020/05/26
9480
执行上下文
解析: a)先填充参数,x:undefined;y:undefined;z:undefined; b)函数申明,在vo对象里有了function fn(){}; c)变量声明,因为变量fn和之前的函数名一样,所以此处的fn变量被忽略。
天天_哥
2018/09/29
6650
面试 | 多线程中的上下文切换
双十一前的一个多月,所有的电商相关的系统都在进行压测,不断的优化系统,我们的电商ERP系统也进行了一个多月的压测和优化的过程,在这其中,我们发现了大量的超时报警,通过工具分析,我们发现是cs指标很高,然后分析日志,我们发现有大量wait()相关的Exception,这个时候我们怀疑是在多线程并发处理的时候,出现了大量的线程处理不及时导致的这些问题,后来我们通过减小线程池最大线程数,再进行压测发现系统的性能有了不小的提升。
故里
2020/11/25
2.1K0
面试 | 多线程中的上下文切换
在多线程构建场景下Powermockito无法在不同类中Mock同一个静态方法
在修改单元测试的过程中,不幸踩了个坑,发现 Powermockito 的PowerMock.mockStatic(ClassThatContainsStaticMethod.class) 在多线程场景下是无法正常工作的,这再次验证了之前 ThrougthWorks 顾问说的那句话:
Allen Cheng
2018/09/10
6K0
Java中什么是多线程中的上下文切换?
在 Java 中,多线程是一个被广泛使用的编程模型,它可以在单个程序中同时执行多个任务,提高程序的并发度和性能。然而,当多条线程同时运行时,操作系统需要对线程进行上下文切换的操作来保证每个线程都能获得足够的CPU时间片以及所需的资源。下面将会详细讲解Java中多线程所涉及的上下文切换的相关知识点。
用户1289394
2023/08/22
3130
Java中什么是多线程中的上下文切换?
JavaScript 中的执行上下文和调用栈是什么
在这篇文章里,我会深入地探讨 JavaScript 中最基本概念之一,那就是执行上下文。通过这篇文章,你应该能够清楚地了解到 JS 解释器究竟在干嘛,为什么可以在一些函数和变量声明之前就能使用,以及它们的值是怎样被决定的。
用户7293182
2022/01/20
7350
JavaScript 中的执行上下文和调用栈是什么
JS 执行上下文
运行JavaScript代码时,当代码执行进入一个环境时,就会为该环境创建一个执行上下文,它会在你运行代码前做一些准备工作,如确定作用域,创建局部变量对象等。
grain先森
2019/03/28
4.2K0
JS 执行上下文
JavaScript执行上下文
JavaScript中的执行上下文是一个抽象的概念,用于描述代码在运行时的环境和状态。执行上下文包含了变量、函数声明、作用域链等信息,它的创建和销毁过程是JavaScript代码执行的基础。
堕落飞鸟
2023/05/17
3090
在GAN中通过上下文的复制和粘贴,在没有数据集的情况下生成新内容
GAN体系结构一直是通过AI生成内容的标准,但是它可以实际在训练数据集中提供新内容吗?还是只是模仿训练数据并以新方式混合功能?
deephub
2020/09/28
1.7K0
在GAN中通过上下文的复制和粘贴,在没有数据集的情况下生成新内容
CREATE2 在广义状态通道中的使用
君士坦丁堡硬升级中引入了一个新操作码 CREATE2[1] ,它使用新的方式来计算常见的合约地址,让生成的合约地址更具有可控性,通过 CREATE2 可以延伸出很多新的玩法,这篇文章来探讨下,在广义状态通道中的妙用。
Tiny熊
2019/10/25
1.4K0
ES 基础 —— 执行上下文
Execution Context(执行上下文)是 ECMA-262 标准中定义的一个抽象概念,用于同 Executable Code(可执行代码)进行区分。
疯狂的技术宅
2019/03/28
6900

相似问题

没有在Ruby线程中执行的代码

23

主线程的执行上下文

32

线程没有执行

21

用于的输出通道的并发(线程执行器)

11

如何使用主动通道对话在通道中启动新线程?

16
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文