8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

@iFrame-resizer/react 实施错误 - 未捕获的语法错误:意外的标记“s”,'scroll-to-top' 不是有效的 JSON

Sefa Dedeoglu 3月前

236 0

我正在使用最新版本的 iframe-resizer/react 来自动调整 iframe 的高度和宽度。每当我对内容做出反应时,我都会收到运行时错误 -VM2860:1

我正在使用最新版本的 iframe-resizer/react 来自动调整 iframe 的高度和宽度。每当我对内容做出反应时,我都会收到运行时错误,指出 -VM2860:1 未捕获的语法错误:意外的令牌“s”,\'scroll-to-top\' 不是有效的 JSON

我不知道这是从哪里来的。我检查了 iframe 中发生的事件。那里也没有提到 scroll-to-top 这个东西。

下面是我编写的代码片段。请帮我解决这个问题。

import IFrameResizer from "@iframe-resizer/react";
<IFrameResizer
          src={iframeSrc}
          license="GPLv3"
          className="iframe-dialog"
          title="Iframe Dialog"
          onLoad={onLoad}
          scrolling={false}
          forwardRef={iframeRef}
          style={{
            width: "100%",
            border: "none",
            opacity: "100",
            height: "100vh",
          }}
 />

我已尝试使用 iframe-resizer/react 中提供的 onResized、onMessage 处理程序来获取消息,但仍然没有任何反应。

帖子版权声明 1、本帖标题:@iFrame-resizer/react 实施错误 - 未捕获的语法错误:意外的标记“s”,'scroll-to-top' 不是有效的 JSON
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Sefa Dedeoglu在本站《typescript》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我有以下 C++ 代码(大大简化):void MyClass::do(){ { std::unique_lock锁定(mtx);而(!完成){...} } std::this_thread::yield(...

    我有以下 C++ 代码(大大简化):

    void MyClass::do()
    {
      {
        std::unique_lock<std::mutex> lock(mtx);
        while (!done)
        {
          ...
        }
      }
      std::this_thread::yield();
    }
    

    此函数由多个线程同时调用,并且在这些线程内循环调用。

    我所期望的(以及我在 Ubuntu 上看到的)是,当我到达 yield() 一个线程时,如果另一个线程在 停止 mutex ,则会发生上下文切换,并且我基本上在两个线程之间来回切换,直到其中一个线程完成。

    我在 Windows 10 上看到的是,第一个线程在第二个线程有机会之前完成(或运行多次迭代)。如果我将 替换为 yield() sleep_for(std::chrono::milliseconds(1)) 我会得到我预期的结果。

    似乎正在发生的事情是, yield() 不会上下文切换到停止的线程 mutex - 即使 mutex 现在已被解锁。

    有谁了解这里发生了什么,以及如何解决这个问题而不必在我的代码中添加睡眠?

  • Stack Overflow 上有几个问题解释了为什么在 Python 中访问全局变量不是线程安全的,即使存在全局解释器锁。原因是

    Stack Overflow 上有几个问题解释了为什么即使存在全局解释器锁,在 Python 中访问全局变量也不是线程安全的。

    原因是 GIL 只允许一个 Python 解释器实例在任何时候执行字节码。但是,由于对内存中数据的许多操作都由多个字节码操作组成(它们不是原子的),如果两个线程切换,其中一个停止运行而另一个恢复运行,则这种情况可能发生在内存中的状态和解释器的状态在同步点不一致的情况下。(想想“竞争条件”。)

    如果以上陈述不是很清楚,这个网站上有一些很好的解释。 下面就是一个例子。

    然而,与此直接相反的是,人们经常说 GIL 的目的是通过防止竞争条件来简化多线程编程。 下面就是一个例子。 但这可能是 - 而且在我看来 - 一种常见的误解或误解 )

    但是,这并不是一个足够详细的解释,因为尽管全局变量没有受到竞争条件保护,但出于上述原因, 有些变量是受到保护的 ,这通常被认为是常识。

    那么 - 为什么访问“非全局”(“某些”)变量可以保证是线程安全的?或者更好的是, 在什么条件下访问变量可以保证是线程安全的?

    一个相对容易理解的例子是局部变量:由于每个函数调用都有自己独立的堆栈框架和一组局部变量,因此显然一个线程不能在局部变量的上下文中与另一个线程产生竞争条件,因为局部变量的生存期仅限于函数调用的生存期。

    换句话说,如果分派多个线程,并且 my_function 该函数调用生命周期内创建的任何变量的入口点都独立于并行运行的所有其他线程。

    作为这个想法的扩展,如果将对(本地或其他)变量的引用传递到同时执行的多个函数中,则不能 保证 是线程安全的,因为两个或多个线程在内存中持有对同一对象的引用。 (这本质上与全局变量示例非常相似。)

    还有其他例子吗?或者这两个例子足以解释必须考虑的一系列可能性吗?

  • 每次我单击当前正在使用的应用程序中的按钮时,程序都会进入“无响应”状态,然后启动其自身的另一个实例,而旧实例仍处于活动状态。我不知道...

    每次我单击当前正在使用的应用程序中的按钮时,程序都会进入“无响应”状态,然后启动其自身的另一个实例,而旧实例仍处于活动状态。我不知道如何或为什么,因为在 IDE 中运行时它可以工作。只要我用 auto-py-to-exe 打包它,它就会这样做。

    按钮的代码:

    info_but = customtkinter.CTkButton(menu,text="", font=custom_font,          
                                    image=info_def,bg_color="#FDF6E4",fg_color="#FDF6E4",hover_color="#3b444b",
                                    width=70, command= info_menu,height=70)
    info_but.place(x=20, y=220)
    
    

    被调用的函数:

    def info_menu():
        global update_label, gpu_label
    
        stop_thread()
        # Beispielverwendung
        os_ver = f"{uname().system} {uname().release}"  # get_gpu_models()
    
        threaded_check_for_new_version(repo_owner, repo_name, current_version)
    
        proc_info = cpuinfo.get_cpu_info()
    
        # RAM Informationen
    
        ram = psutil.virtual_memory()
    
        for child in frame.winfo_children():
            child.destroy()
    
        content_frame = customtkinter.CTkFrame(frame, width=880, height=600)
        content_frame.place(x=0, y=0)
    
        label = customtkinter.CTkLabel(content_frame, text=f"General Information:",anchor="w", justify="left", width=200, height=30, font=custom_font2)
        label.grid(row=0, column=0, padx=(10,10),pady=(10,30))
    
        label = customtkinter.CTkLabel(content_frame, text=f"App version:",anchor="w", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=2, column=0, padx=(150,10),pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"{current_version}",anchor="w", width=130, height=20,font=custom_font)
        label.grid(row=2, column=1, padx=360,pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"Build date:",anchor="w", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=3, column=0, padx=(150,10),pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"05/2024",anchor="w", width=130, height=20,font=custom_font)
        label.grid(row=3, column=1, padx=360,pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"Publisher:",anchor="w", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=4, column=0, padx=(150,10),pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"",anchor="w", width=130, height=20,font=custom_font)
        label.grid(row=4, column=1, padx=360,pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"Update avaiable:",anchor="w", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=5, column=0, padx=(150,10),pady=10)
    
        update_label = customtkinter.CTkLabel(content_frame, text=f"Working"
                                       ,anchor="w", width=130, height=20,font=custom_font)
        update_label.grid(row=5, column=1, padx=360,pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"Authentic:",anchor="w", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=6, column=0, padx=(150,10),pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"Yes",anchor="w", width=130, height=30,font=custom_font)
        label.grid(row=6, column=1, padx=360,pady=10)
    
    
        label = customtkinter.CTkLabel(content_frame, text=f"System Information:",anchor="w", justify="left", width=200, height=30, font=custom_font2)
        label.grid(row=7, column=0, padx=(10,10),pady=(20,10))
    
    
        label = customtkinter.CTkLabel(content_frame, text=f"CPU Model:",anchor="w", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=10, column=0, padx=(150,10),pady=10)
    
    
        label = customtkinter.CTkLabel(content_frame, text=f"{'{0}'.format(proc_info['brand_raw'])}",anchor="w", width=130, height=20,font=custom_font,wraplength=130)
        label.grid(row=10, column=1, padx=360,pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"Architecture:",anchor="w", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=9, column=0, padx=(150,10),pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"{'{0}'.format(proc_info['arch'])}",anchor="w", width=130, height=20,font=custom_font)
        label.grid(row=9, column=1, padx=360,pady=10)
    
    
        label = customtkinter.CTkLabel(content_frame, text=f"OS:",anchor="w", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=8, column=0, padx=(150,10),pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"{os_ver}",anchor="w", width=130, height=20,font=custom_font)
        label.grid(row=8, column=1, padx=360,pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"GPU:",anchor="w", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=11, column=0, padx=(150,10),pady=10)
    
        gpu_label = customtkinter.CTkLabel(content_frame, text=f"Working",anchor="w", width=130, height=20,font=custom_font)
        gpu_label.grid(row=11, column=1, padx=360,pady=10)
    
    
        label = customtkinter.CTkLabel(content_frame, text=f"Avaiable RAM:",anchor="nw", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=12, column=0, padx=(150,10),pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"{str(ram.total / 1024**3)[:4]} GB",anchor="w", width=130, height=20,font=custom_font)
        label.grid(row=12, column=1, padx=360,pady=(10,10))
    
        label = customtkinter.CTkLabel(content_frame, text=f"",anchor="nw", width=130, justify="left", height=20,font=custom_font)
        label.grid(row=13, column=0, padx=(150,10),pady=10)
    
        label = customtkinter.CTkLabel(content_frame, text=f"",anchor="w", width=130, height=20,font=custom_font)
        label.grid(row=13, column=1, padx=360,pady=(10,10))
    
        threaded_get_gpu_models(gpu_label)
    

    影响:

    def fetch_latest_version(repo_owner, repo_name, current_version):
        global cached_result
        url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/releases/latest"
        response = requests.get(url)
        if response.status_code == 200:
            latest_version = response.json().get('tag_name')
            comparison_result = semver.compare(current_version, latest_version)
            if comparison_result < 0:
                cached_result = [True, latest_version]
            elif comparison_result == 0:
                cached_result = [False, latest_version]
            else:
                cached_result = [False, current_version]  # Deine Version ist neuer
        else:
            cached_result = [False, None]
    
        update_label_text()
    
    
    def update_label_text():
        global cached_result, update_label
        if cached_result[0]:
            update_label.configure(text="Yes")
        else:
            if cached_result[1] is None:
                update_label.configure(text="Error")
            else:
                update_label.configure(text="No")
        root.update()
    
    
    def check_for_new_version(repo_owner, repo_name, current_version):
        global cached_result, cache_lock
        root.update()
        with cache_lock:
            if cached_result[1] is None:
                fetch_latest_version(repo_owner, repo_name, current_version)
            else:
                update_label_text()
    
    
    def threaded_check_for_new_version(repo_owner, repo_name, current_version):
        thread = threading.Thread(target=check_for_new_version, args=(repo_owner, repo_name, current_version))
        thread.start()
    
    
    def fetch_gpu_models(result):
        try:
            gpus = GPUtil.getGPUs()
            gpu_models = set(gpu.name for gpu in gpus)
            result.append(list(gpu_models) if gpu_models else ["Unknown"])
        except Exception as e:
            result.append(["Unknown"])
        update_model_label(gpu_label,result[0])
    
    
    def update_model_label(gpu_label,gpu_models):
        gpu_label.configure(text=f"{gpu_models[0]}")
        root.update()
    
    
    def get_gpu_models(gpu_label):
        result = []
        fetch_gpu_models(result)
        return result[0] if result else ["Unknown"]
    
    
    def threaded_get_gpu_models(gpu_label):
        thread = threading.Thread(target=get_gpu_models, args=(gpu_label,))
        thread.start()
    

    我修复了单击按钮时 IDE 抛出的所有错误,例如线程处理等,但仍然没有成功。我还更改了变量和函数的名称,因为我注意到我(愚蠢地)多次将这个名称用于不同的事物。

    stop_thread 不是罪魁祸首,因为它是在错误发生之后添加的。

  • KcH 3月前 0 只看Ta
    引用 4

    如何在 Java 中实现自定义 ReadWriteLock,使线程能够将读锁升级为写锁,而不会产生死锁风险?

    如何在 Java 中实现自定义 ReadWriteLock,使线程能够将读锁升级为写锁,而不会产生死锁风险?

  • 我对现代 C++ 不太熟悉,但我一直在查看 Boost.Beast 示例文件并试图了解它们的工作原理。具体来说,我一直在查看这个 http 服务器示例。这里...

    我对现代 C++ 不太熟悉,但我一直在查看 Boost.Beast 示例文件并试图了解它们的工作原理。

    具体来说,我一直在看 这个 http 服务器示例 .

    以下是我想要理解的简化版本:

    void do_session(
        tcp::socket& socket,
        ssl::context& ctx,
        std::shared_ptr<std::string const> const& doc_root
    );
    
    
    int main(int argc, char* argv[])
    {
        if (argc != 4)
        {
            std::cerr <<
                "Usage: http-server-sync-ssl <address> <port> <doc_root>\n" <<
                "Example:\n" <<
                "    http-server-sync-ssl 0.0.0.0 8080 .\n";
            return EXIT_FAILURE;
        }
        auto const address = net::ip::make_address(argv[1]);
        auto const port = static_cast<unsigned short>(std::atoi(argv[2]));
        auto const doc_root = std::make_shared<std::string>(argv[3]);
    
        net::io_context ioc{1};
        ssl::context ctx{ssl::context::tlsv12};
        load_server_certificate(ctx);
        tcp::acceptor acceptor{ioc, {address, port}};
    
        for(;;)
        {
            // This will receive the new connection
            tcp::socket socket{ioc};
    
            // Block until we get a connection
            acceptor.accept(socket);
    
            // Launch the session, transferring ownership of the socket
            std::thread{std::bind(
                &do_session,
                std::move(socket),
                std::ref(ctx),
                doc_root)}.detach();
        }
    }
    

    在底层,当创建线程时, &do_session 在传递给构造函数之前 std::bind 被包装起来 std::thread 。据我所知,参数可以传递到线程构造函数中。仅仅写 会不会有功能或性能上的差异 std::thread(&do_session, std::move(socket), std::ref(ctx), doc_root)

    我原以为这两者在功能上是相同的,但我假设该文件的作者知道一些我不知道的事情……

  • 我有一个 react.js 应用程序,它作为小部件添加到我们客户的网站。客户的网站可以使用任何工具构建,例如 wordress / angular / react 等。我们有两种类型的小部件:搜索和

    我有一个 react.js 应用程序,它作为小部件添加到我们客户的网站。客户的网站可以使用任何工具构建,例如 wordress / angular / react 等。

    我们有两种类型的小部件: search chat 。我对两者都使用一个存储库,生成两个单独的版本,并托管在 aws s3 上。

    在客户的网站上,我们只需添加托管在 s3 上的构建的 index.js 和 index.css 文件的脚本和样式表。到目前为止,它运行良好。这是我们的示例构建:

    在我的应用中,我们可以根据客户的需求延迟加载多个网格(例如,在上面的构建中,您可以看到旅行网格被延迟加载)。我们需要这样做,以便我们的构建大小不会增加太多,并且在任何单个客户的站点上,仅加载与该客户相关的网格。

    在客户网站上 search build chat build ,一切都正常

    下面是一个延迟加载行程网格的加载器示例:

    import React, { Suspense, useMemo } from 'react'
    
    // Utility function to lazy load the component
    const getTripGridLazyLoaded = async organizationSlug => {
      switch (organizationSlug) {
        case 'clientA':
          return await import('./clientA/TripsGrid')
        case 'clientB':
          return await import('./clientB/TripsGrid')
        default:
          return await import('./common/TripsGrid')
      }
    }
    
    const TripsGridLoader = ({
      id,
      items,
      title,
      isLessThanLaptop,
      router,
      language,
      random_match,
      showRelevancyInfo,
      organizationSlug,
      itemsPerRow,
      itemsPerPage,
      isChatMode,
    }) => {
      // Memoize the lazy-loaded component based on organizationSlug
      const TripGridLazyLoaded = useMemo(() => {
        if (!organizationSlug) return null
        return React.lazy(() => getTripGridLazyLoaded(organizationSlug))
      }, [organizationSlug])
    
      return (
        <>
          <Suspense fallback={<></>}>
            <TripGridLazyLoaded
              id={id}
              title={title}
              items={items}
              random_match={random_match}
              isLessThanLaptop={isLessThanLaptop}
              router={router}
              language={language}
              showRelevancyInfo={showRelevancyInfo}
              organizationSlug={organizationSlug}
              itemsPerRow={itemsPerRow}
              itemsPerPage={itemsPerPage}
              isChatMode={isChatMode}
            />
          </Suspense>
        </>
      )
    }
    
    export default TripsGridLoader
    

    以下是行程网格的代码示例:

    import React, { useState, useEffect } from 'react'
    import { GridWrapper, ItemsWrapper } from './style'
    import TripItem from './TripItem'
    import { GridTitle, GridSubtitle, ShowMoreCta } from './style'
    import { TRANSLATIONS_TEXTS } from '../../../../utils/constants'
    
    const TripsGrid = ({
      id,
      items,
      title,
      isLessThanLaptop,
      router,
      language,
      random_match,
      showRelevancyInfo,
      itemsPerRow,
      itemsPerPage,
      isChatMode,
    }) => {
      const [currentIsLessThanLaptop, setIsCurrentIsLessThanLaptop] =
        useState(false)
      const [itemsToShow, setItemsToShow] = useState(0)
      const [gridId, setGridId] = useState(null)
    
      useEffect(() => {
        if (isLessThanLaptop) setIsCurrentIsLessThanLaptop(isLessThanLaptop)
      }, [isLessThanLaptop])
    
      useEffect(() => {
        if (id !== gridId) {
          setGridId(id)
          setItemsToShow(itemsPerPage)
        }
      }, [id])
    
      if (!items?.length) return null
    
      const getItems = () => {
        const slicedItemsToShow = items.slice(0, itemsToShow)
    
        let itemsToReturn = slicedItemsToShow?.map((item, i) => {
          return (
            <TripItem
              key={item.id || item.url + item?.name}
              isLessThanLaptop={currentIsLessThanLaptop}
              router={router}
              item={item}
              language={language}
              showRelevancyInfo={showRelevancyInfo}
              randomMatch={random_match}
              itemsPerRow={itemsPerRow}
            />
          )
        })
    
        return itemsToReturn
      }
    
      if (getItems().length) {
        return (
          <GridWrapper id='grid-wrapper-trip'>
            <GridTitle $padding={'0px 15px 0px 0px'} isChatMode={isChatMode}>
              {title}
            </GridTitle>
            <ItemsWrapper id='grid-trip-items-wrapper'>{getItems()}</ItemsWrapper>
            {itemsToShow < items.length ? (
              <ShowMoreCta
                onClick={() => {
                  setItemsToShow(itemsToShow + itemsPerPage)
                }}
              >
                {TRANSLATIONS_TEXTS.show_more[language]}
              </ShowMoreCta>
            ) : null}
          </GridWrapper>
        )
      } else return null
    }
    
    export default TripsGrid
    
    

    当旅行网格(或任何其他网格延迟加载)时,我收到以下错误,此外,这些错误有时似乎是随机发生的。

    我研究了这个问题,花了好几个小时。根据 这里的 ,这是由于错误的钩子调用或 React 版本不匹配错误造成的。

    • 我已经通过日志检查了 React 版本在应用程序加载时间和延迟加载组件的加载时间上是否相同 console.log(React.version)
    • 使用两个小部件中的一个时不存在错误,这令人 search 困惑 chat
    • 我已经添加了代码。看起来我没有任何错误的钩子调用

    如果我这样做是 npm ls react 为了查看我的应用中是否有多个版本的 React,那么我得到的只有一个版本。输出如下:

    enter image description here

    请注意,当我不像这样延迟加载行程网格(或任何其他网格)时,它也能正常工作:

    import React, { useMemo } from 'react'
    import Common from './common/TripsGrid'
    import ClientA from './clientA/TripsGrid'
    import ClientB from './clientB/TripsGrid'
    
    const TripsGridLoader = ({
      id,
      items,
      title,
      isLessThanLaptop,
      router,
      language,
      random_match,
      showRelevancyInfo,
      organizationSlug,
      itemsPerRow,
      itemsPerPage,
      isChatMode,
    }) => {
      // Memoize the lazy-loaded component based on organizationSlug
      const TripGridLazyLoaded = useMemo(() => {
        if (!organizationSlug) return null
        switch (organizationSlug) {
          case 'clientA':
            return ClientA
          case 'clientB':
            return ClientB
          default:
            return Common
        }
      }, [organizationSlug])
    
      return (
        <>
          <TripGridLazyLoaded
            id={id}
            title={title}
            items={items}
            random_match={random_match}
            isLessThanLaptop={isLessThanLaptop}
            router={router}
            language={language}
            showRelevancyInfo={showRelevancyInfo}
            organizationSlug={organizationSlug}
            itemsPerRow={itemsPerRow}
            itemsPerPage={itemsPerPage}
            isChatMode={isChatMode}
          />
        </>
      )
    }
    
    export default TripsGridLoader
    

    谁能给我指出正确的方向?

  • 声明函数 f(fun: (t:T) => void): voidf((t) => { 类型 T = typeof t 类型 IsStringArray = T[] 扩展了 string[] ? true : false // false})函数 g (时间:时间){...

    declare function f(fun: <T>(t: T) => void): void
    f((t) => {
        type T = typeof t
        type IsStringArray = T[] extends string[] ? true : false // false
    
    })
    
    function g<T>(t: T) {
        type IsStringArray = T[] extends string[] ? true : false // T[] extends string[] ? true : false
    }
    

    IsStringArray false 的参数中 f ,而 T extends string[] ? true : false 在的主体中 g .

    有什么区别呢?

    https://www.typescriptlang.org/play/?#code/CYUwxgNghgTiAEAzArgOzAFwJYHtVIAoVUAueAHgBUA+AjMygSngF5r4A3HLYRsrngChEBOszbwA3oPiz4GAJ4AHBJVbzlIHInky5ilfACSAZwDKGGFlQBzAIIwYUBesoBtALrwQAD wwhUYBN4E0trG094AH55GGQEMkQoCBMEAHo0pGTUwUEAX0Zc4kxcfBsqWnp4Jik9WQMEUwsrWwcnFxZqyN9-QODQloivGMt4+ETs9Mz3Lx6AoJCw20iRuISslJB8oA

  • 是的 - 我在这里有点理解字里行间的意思,但我认为在这种情况下,某些操作的字节码本质上保证是“有效原子的”,这意味着解释器在执行这些字节码操作的过程中不能切换线程。这样说对吗?

  • 并且,谈到 3.13 版中将提供的“无 GIL”Python:开发人员正在寻找提高性能的方法,因此即使没有 GIL 的版本也一定会保留相同的保证,即内置数据结构中的操作将继续是线程安全的。从 Python 开发人员的角度来看,除了多线程 Python 进程能够利用所有 CPU 核心之外,什么都不会改变。扩展开发人员(使用本机代码的 Python 项目)将发生一些重大变化。

  • python 字节码与 Java 字节码不同:虽然我可以想象 Java 中的 Python 列表之类的结构将使用 JVM 操作码来执行非常基本的操作(检查保留长度、重新分配内存等...),但 Python VM 字节码是非常高级的,而较低级别的操作以本机代码运行(在 CPython 中用 C 编写)

  • 它很可能是一个字节码 - 但这并不重要,正如我所说 - 重要的是 Python 中现成的线程安全性是这样的:方法提供的操作(特殊的,如 __setitem__l 或其他,如 .append )是线程安全的:如果需要,附加到列表将会增加它,更改其内部长度属性,并由于 GIL,在线程安全的操作中将新值写入末尾。

  • 为什么您描述的那些特定操作本质上是线程安全的?例如,我猜想,附加到列表需要执行一长串字节码。(如果不是这种情况,那将非常令人惊讶。)GIL 的工作原理如何确保这是线程安全的?

  • 引用 14

    假设你的线程 R 刚刚 释放了 mtx ,而你的线程 W 正在 等待 mtx 现在,线程 R 调用 yield() .

    1. p1

    2. p2

    3. p3

    这个故事的寓意是, yield 按照预期的方式使用它。使用它来标记程序产生当前时间片的“好”位置,但不要 依赖 它做任何事情。


    更新:

    1. 您的程序是否在多 CPU 主机上运行?并且其中一个或多个 CPU 是否空闲?如果是这样,则 yield 无需结束时间片,因为调度程序可能已经选择在当前空闲的处理器上“唤醒”线程 W。但在这种情况下...

    ...假设线程 A 绕过最外层循环,并回到 mtx 再次 ,然后 线程 W 才能完全“醒来”并 mtx 自行抓取。这是另一种可能性。


    *不要忘记可能属于各种操作系统服务的所有线程,如果是 Linux,请不要忘记内核线程。

  • Matt 3月前 0 只看Ta
    引用 15

    我认为您把情况复杂化了,而实际上这些情况是相当直观的。

    如果某个资源被可能同时运行的代码引用(可能是在另一个线程、另一个异步任务中,甚至是具有多处理的托管对象中),则对该资源的任何修改都必须使用适当的锁进行保护。(语言中针对每种情况都有不同的锁)。

    任何原子操作的语言都没有任何保证,因为这并不重要,也不可能重要,给定操作需要执行多少字节码指令 - 即使是 += 整数运算符也不是线程安全的(因为读取旧值,计算新值并分配给旧名称)。

    您在文中所说的“线程安全”只是其他并发代码不会影响的简单隔离上下文 - 正如我所说,这非常直观。对于跨并发代码共享的任何可变资源,都存在“线程不安全”,除非使用显式方法确保事务隔离。(请注意,在异步编程的情况下,只需避免任何 await , async for and async with 语句即可确保您的代码是任何时候对给定值进行操作的唯一代码 - 几乎不需要显式锁定)

    谈到 GIL,正如评论中所说:它使 Python 运行时本身的实现更加容易。对内置数据类型的操作(例如附加到列表或在字典中创建新键)是 Python 中自然线程安全的操作。(但如果您需要从这些结构中读取值、对其进行操作并将其写回,则只需使用适当的锁)

  • 我觉得你应该打电话

  • Zch 3月前 0 只看Ta
    引用 17

    Windows 内核进行调度,当一个线程放弃其时间片并且没有其他线程等待时,同一个线程将获得时间片。也许这就是您所观察到的。

  • 引用 18

    我认为 info_menu 仅包含标签位置的信息就足够了,因为我非常有信心这些没有问题 :(。我认为问题一定出在块 2 或 3 中的函数上。这是 info_menu 中发生的唯一 \'active\' 的事情。我会尝试添加该功能作为答案

  • 当然,我是以熟悉互斥锁和锁但不熟悉 Python 内部实现的人的身份提出这个问题的。我读到的关于 GIL 和线程安全的许多内容很可能都是误解,因为在很多情况下,我毫不怀疑,撰写我读过的文章的人也没有深入或详细地了解 Python 的实现方式以及 GIL 的作用/不作用。

  • Lucy 3月前 0 只看Ta
    引用 20

    仅是一个提示,其效果是由实现定义的。

返回
作者最近主题: