Threads в процессоре что это
Перейти к содержимому

Threads в процессоре что это

  • автор:

Процессы и потоки in-depth. Обзор различных потоковых моделей

Здравствуйте дорогие читатели. В данной статье мы рассмотрим различные потоковые модели, которые реализованы в современных ОС (preemptive, cooperative threads). Также кратко рассмотрим как потоки и средства синхронизации реализованы в Win32 API и Posix Threads. Хотя на Хабре больше популярны скриптовые языки, однако основы — должны знать все 😉

Потоки, процессы, контексты.

Системный вызов (syscall). Данное понятие, вы будете встречать достаточно часто в данной статье, однако несмотря на всю мощь звучания, его определение достаточно простое 🙂 Системный вызов — это процесс вызова функции ядра, из приложение пользователя. Режим ядра — код, который выполняется в нулевом кольце защиты процессора (ring0) с максимальными привилегиями. Режим пользователя — код, исполняемый в третьем кольце защиты процессора (ring3), обладает пониженными привилегиями. Если код в ring3 будет использовать одну из запрещенных инструкций (к примеру rdmsr/wrmsr, in/out, попытку чтения регистра cr3, cr4 и т.д.), сработает аппаратное исключение и пользовательский процесс, чей код исполнял процессор в большинстве случаях будет прерван. Системный вызов осуществляет переход из режима ядра в режим пользователя с помощью вызова инструкции syscall/sysenter, int2eh в Win2k, int80h в Linux и т.д.

И так, что же такое поток? Поток (thread) — это, сущность операционной системы, процесс выполнения на процессоре набора инструкций, точнее говоря программного кода. Общее назначение потоков — параллельное выполнение на процессоре двух или более различных задач. Как можно догадаться, потоки были первым шагом на пути к многозадачным ОС. Планировщик ОС, руководствуясь приоритетом потока, распределяет кванты времени между разными потоками и ставит потоки на выполнение.

На ряду с потоком, существует также такая сущность, как процесс. Процесс (process) — не что более иное, как некая абстракция, которая инкапсулирует в себе все ресурсы процесса (открытые файлы, файлы отображенные в память. ) и их дескрипторы, потоки и т.д. Каждый процесс имеет как минимум один поток. Также каждый процесс имеет свое собственное виртуальное адресное пространство и контекст выполнения, а потоки одного процесса разделяют адресное пространство процесса.

  • Регистры процессора.
  • Указатель на стек потока/процесса.
  • Если ваша задача требует интенсивного распараллеливания, используйте потоки одного процесса, вместо нескольких процессов. Все потому, что переключение контекста процесса происходит гораздо медленнее, чем контекста потока.
  • При использовании потока, старайтесь не злоупотреблять средствами синхронизации, которые требуют системных вызовов ядра (например мьютексы). Переключение в редим ядра — дорогостоящая операция!
  • Если вы пишете код, исполняемый в ring0 (к примеру драйвер), старайтесь обойтись без использования дополнительных потоков, так как смена контекста потока — дорогостоящая операция.

Классификация потоков

  • По отображению в ядро: 1:1, N:M, N:1
  • По многозадачной модели: вытесняющая многозадачность (preemptive multitasking), кооперативная многозадачность (cooperative multitasking).
  • По уровню реализации: режим ядра, режим польователя, гибридная реализация.

Классификация потоков по отображению в режим ядра

  • Центральный планировщик ОС режима ядра, который распределяет время между любым потоком в системе.
  • Планировщик библиотеки потоков. У библиотеки потоков режима пользователя может быть свой планировщик, который распределяет время между потоками различных процессов режима пользователя.
  • Планировщик потоков процесса. Уже рассмотренные нами волокна, ставятся на выполнение именно таким способом. К примеру свой Thread Manager есть у каждого процесса Mac OS X, написанного с использованием библиотеки Carbon.

Модель N:M отображает некоторое число потоков пользовательских процессов N на M потоков режима ядра. Проще говоря имеем некую гибридную систему, когда часть потоков ставится на выполнение в планировщике ОС, а большая их часть в планировщике потоков процесса или библиотеки потоков. Как пример можно привести GNU Portable Threads. Данная модель достаточно трудно реализуема, но обладает большей производительностью, так как можно избежать значительного количества системных вызовов.

Модель N:1. Как вы наверное догадались — множество потоков пользовательского процесса отображаются на один поток ядра ОС. Например волокна.

Классификация потоков по многозадачной модели

Во времена DOS, когда однозадачные ОС перестали удовлетворять потребителя, программисты и архитекторы задумали реализовать многозадачную ОС. Самое простое решение было следующим: взять общее количество потоков, определить какой-нибудь минимальный интервал выполнения одного потока, да взять и разделить между всеми -братьями- потоками время выполнения поровну. Так и появилось понятие кооперативной многозадачности (cooperative multitasking), т.е. все потоки выполняются поочередно, с равным временем выполнения. Никакой другой поток, не может вытеснить текущий выполняющийся поток. Такой очень простой и очевидный подход нашел свое применение во всех версиях Mac OS вплоть до Mac OS X, также в Windows до Windows 95, и Windows NT. До сих пор кооперативная многозадачность используется в Win32 для запуска 16 битных приложений. Также для обеспечения совместимости, cooperative multitasking используется менеджером потоков в Carbon приложениях для Mac OS X.

Однако, кооперативная многозадачность со временем показала свою несостоятельность. Росли объемы данных хранимых на винчестерах, росла также скорость передачи данных в сетях. Стало понятно, что некоторые потоки должны иметь больший приоритет, как-то потоки обслуживания прерываний устройств, обработки синхронных IO операций и т.д. В это время каждый поток и процесс в системе обзавелся таким свойством, как приоритет. Подробнее о приоритетах потоков и процессов в Win32 API вы можете прочесть в книге Джефри Рихтера, мы на этом останавливатся не будем 😉 Таким образом поток с большим приоритетом, может вытеснить поток с меньшим. Такой прицип лег в основу вытесняющей многозадачности (preemptive multitasking). Сейчас все современные ОС используют данный подход, за исключением реализации волокон в пользовательском режиме.

Классификация потоков по уровню реализации

  1. Реализация потоков на уровне ядра. Проще говоря, это классическая 1:1 модель. Под эту категорию подпадают:
    • Потоки Win32.
    • Реализация Posix Threads в Linux — Native Posix Threads Library (NPTL). Дело в том, что до версии ядра 2.6 pthreads в Linux был целиком и полностью реализован в режиме пользователя (LinuxThreads). LinuxThreads реализовывалf модель 1:1 следующим образом: при создании нового потока, библиотека осуществляла системный вызов clone, и создавало новый процесс, который тем не менее разделял единое адресное пространство с родительским. Это породило множество проблем, к примеру потоки имели разные идентификаторы процесса, что противоречило некоторым аспектам стандарта Posix, которые касаются планировщика, сигналов, примитивов синхронизации. Также модель вытеснения потоков, работала во многих случаях с ошибками, по этому поддержку pthread решено было положить на плечи ядра. Сразу две разработки велись в данном направлении компаниями IBM и Red Hat. Однако, реализация IBM не снискала должной популярности, и не была включена ни в один из дистрибутивов, потому IBM приостановила дальнейшую разработку и поддержку библиотеки (NGPT). Позднее NPTL вошли в библиотеку glibc.
    • Легковесные ядерны потоки (Leight Weight Kernel Threads — LWKT), например в DragonFlyBSD. Отличие этих потоков, от других потоков режима ядра в том, что легковесные ядерные потоки могут вытеснять другие ядерные потоки. В DragonFlyBSD существует множество ядерных потоков, например поток обслуживания аппаратных прерываний, поток обслуживания программных прерываний и т.д. Все они работают с фиксированным приоритетом, так вот LWKT могут вытеснять эти потоки (preempt). Конечно это уже более специфические вещи, про которые можно говорить бесконечно, но приведу еще два примера. В Windows все потоки ядра выполняются либо в контексте потока инициировавшего системный вызов/IO операцию, либо в контексте потока системного процесса system. В Mac OS X существует еще более интересная система. В ядре есть лишь понятие task, т.е. задачи. Все операции ядра выполняются в контексте kernel_task. Обработка аппаратного прерывания, к примеру, происходит в контексте потока драйвера, который обслуживает данное прерывание.
  2. Реализация потоков в пользовательском режиме. Так как, системный вызов и смена контекста — достаточно тяжелые операции, идея реализовать поддержку потоков в режиме пользователя витает в воздухе давно. Множество попыток было сделано, однако данная методика популярности не обрела:
    • GNU Portable Threads — реализация Posix Threads в пользовательском режиме. Основное преимущество — высокая портабельность данной библиотеки, проще говоря она может быть легко перенесена на другие ОС. Проблему вытиснения потоков в данной библиотеке решили очень просто — потоки в ней не вытесняются 🙂 Ну и конечно ни о какой мультмпроцессорности речь идти не может. Данная библиотека реализует модель N:1.
    • Carbon Threads, которые я упоминал уже не раз, и RealBasic Threads.
  3. Гибридная реализация. Попытка использовать все преимущества первого и второго подхода, но как правило подобные мутанты обладают гораздо бОльшими недостатками, нежели достоинствами. Один из примеров: реализация Posix Threads в NetBSD по модели N:M, которая была посже заменена на систему 1:1. Более подробно вы можете прочесть в публикации Scheduler Activations: Effective Kernel Support for the User-Level Management of Parallelism.

Win32 API Threads

Если вы все еще не устали, предлагаю небольшой обзор API для работы с потоками и средствами синхронизации в win32 API. Если вы уже знакомы с материалом, можете смело пропускать этот раздел 😉

Потоки в Win32 создаются с помощью функции CreateThread, куда передается указатель на функцию (назовем ее функцией потока), которая будет выполнятся в созданом потоке. Поток считается завершенным, когда выполнится функция потока. Если же вы хотите гарантировать, что поток завершен, то можно воспользоватся функцией TerminateThread, однако не злоупотребляйте ею! Данная функция «убивает» поток, и отнюдь не всегда делает это корректно. Функция ExitThread будет вызвана неявно, когда завершится функция потока, или же вы можете вызвать данную функцию самостоятельно. Главная ее задача — освободить стек потока и его хендл, т.е. структуры ядра, которые обслуживают данный поток.

Поток в Win32 может пребывать в состоянии сна (suspend). Можно «усыпить поток» с помощью вызова функции SuspendThread, и «разбудить» его с помощью вызова ResumeThread, также поток можно перевести в состояние сна при создании, установив значение параметра СreateSuspended функции CreateThread. Не стоит удивлятся, если вы не увидите подобной функциональности в кроссплатформенных библиотеках, типа boost::threads и QT. Все очень просто, pthreads просто не поддерживают подобную функциональность.

Средства синхронихации в Win32 есть двух типов: реализованные на уровне пользователя, и на уровне ядра. Первые — это критические секции (critical section), к второму набору относят мьютексы (mutex), события (event) и семафоры (semaphore).

Критические секции — легковесный механизм синхронизации, который работает на уровне пользовательского процесса и не использует тяжелых системных вызовов. Он основан на механизме взаимных блокировок или спин локов (spin lock). Поток, который желает обезопасить определенные данные от race conditions вызывает функцию EnterCliticalSection/TryEnterCriticalSection. Если критическая секция свободна — поток занимает ее, если же нет — поток блокируется (т.е. не выполняется и не отъедает процессорное время) до тех пор, пока секция не будет освобождена другим потоком с помощью вызова функции LeaveCriticalSection. Данные функции — атомарные, т.е. вы можете не переживать за целостность ваших данных 😉

  • Они использует примитивы ядра при выполнении, т.е. системные вызовы, что сказывается не производительности.
  • Могут быть именованными и не именованными, т.е. каждому такому объекту синхронизации можно присвоить имя.
  • Работают на уровне системы, а не на уровне процесса, т.е. могут служить механизмом межпроцессного взаимодействия (IPC).
  • Используют для ожидания и захвата примитива единую функцию: WaitForSingleObject/WaitForMultipleObjects.

Posix Threads или pthreads

Сложно представить, какая из *nix подобных операционных систем, не реализует этот стандарт. Стоит отметить, что pthreads также используется в различных операционных системах реального времени (RTOS), потому требование к этой библиотеке (вернее стандарту) — жестче. К примеру, поток pthread не может пребывать в состоянии сна. Также в pthread нет событий, но есть гораздо более мощный механизм — условных переменных (conditional variables), который с лихвой покрывает все необходимые нужды.

Поговорим об отличиях. К примеру, поток в pthreads может быть отменен (cancel), т.е. просто снят с выполнения посредством системного вызова pthread_cancel в момент ожидания освобождения какого-нибудь мьютекса или условной переменной, в момент выполнения вызова pthread_join (вызывающий поток блокируется до тех пор, пока не закончит свое выполнение поток, приминительно к которому была вызвана функция) и т.д. Для работы с мьютексами и семафорами существует отдельные вызовы, как-то pthread_mutex_lock/pthread_mutex_unlock и т.д.

Conditional variables (cv) обычно используется в паре с мьютексами в более сложных случаях. Если мьютекс просто блокирует поток, до тех пор, пока другой поток не освободит его, то cv создают условия, когда поток может заблокировать сам себя до тех пор, пока не произойдет какое-либо условия разблокировки. Например, механизм cv помогает эмулировать события в среде pthreads. Итак, системный вызов pthread_cond_wait ждет, пока поток не будет уведомлен о том, что случилось определенное событие. pthread_cond_signal уведомляет один поток из очереди, что cv сработала. pthread_cond_broadcast уведомляет все потоки, которые вызывали pthread_cond_wait, что сработала cv.

Прощальное слово

На сегодня пожалуй все, иначе информации станет слишком много. Для интересующихся, есть несколько полезных ссылок и книг внизу 😉 Также высказывайте свое мнение, интересны ли вам статьи по данной теме.

UPD: дополнил статью небольшой информацией о режиме ядра и режиме пользователя.
UPD2: исправил досадные промахи и ошибки. Спасибо комментаторам 😉

Что важнее для процессора? Количество ядер или потоков?

Процессорные ядра против потоков — это вопрос, который до сих пор грызет энтузиастов и любителей ПК. Что важнее для хорошего процессора, количество ядер или потоков? Что ж, как и следовало ожидать, на этот вопрос нельзя дать прямой ответ. Потоки в основном помогают ядрам обрабатывать информацию более эффективным образом. При этом потоки ЦП приносят реальную видимую производительность в очень специфических задачах, поэтому гиперпоточный ЦП не всегда может помочь вам достичь лучших результатов.

Что такое центральный процессор?

Процессор (центральный процессор) является ядром каждого смартфона, планшета, компьютера и сервера. Это критически важный компонент, который определяет, как ваш компьютер будет работать, и определяет, насколько хорошо он может выполнять свою работу.

Процессор принимает основные инструкции, которые вы вводите на своем компьютере, и распределяет эти задания по другим чипам в вашей системе. Перераспределяя сложные задачи на микросхемы, лучше всего оборудованные для их обработки, он позволяет вашему компьютеру работать на пиковом уровне.

Процессор иногда называют мозгом компьютера. Он расположен на материнской плате (также называемой основной платой) и является отдельным компонентом от компонента памяти.

Он действует на компонент памяти, который хранит все данные и информацию в вашей системе. Компонент памяти и процессор отделены от вашей видеокарты. Единственная функция видеокарты состоит в том, чтобы получать данные и преобразовывать их в изображения, которые вы видите на мониторе.

С развитием технологий из года в год, мы видим, что процессоры становятся все меньше и меньше. И они работают быстрее, чем когда-либо прежде. Вы поймете что значит быстрее, если узнаете кое-что о законе Мура, который получил свое название от соучредителя Intel Гордона Мура. Мур считает, что число транзисторов в интегральной схеме удваивается каждые два года.

Что делает процессор?

Как мы уже говорили ранее, процессор — это мозг вашего компьютера. Он берет данные из определенной программы или приложения, выполняет серию вычислений и выполняет команду. Он выполняет цикл из трех частей, иначе называемый повторяющимся циклом извлечения, декодирования и выполнения. На первом этапе процессор выбирает инструкции из памяти вашей системы. Как только он получает инструкции из памяти, он переходит ко второму этапу. Именно на этом втором этапе он декодирует эти инструкции.

Как только машина расшифровывает инструкции, она переходит к третьему этапу выполнения. Декодированная информация проходит через ЦП, чтобы достичь блоков, которые фактически должны выполнять требуемую функцию. В процессе декодирования он выполняет математические уравнения для отправки требуемого сигнала в вашу систему.

Этот цикл повторяется снова и снова для каждого действия и команды, которые вы выполняете. Процессор является важной частью любой системы, и он тесно работает с потоками. Различные процессоры имеют различное количество потоков, чтобы ограничить или увеличить производительность вашего компьютера.

Что же такое многопоточность?

Поток — это небольшая последовательность запрограммированных инструкций. Потоки относятся к наивысшему уровню кода, который может выполнять ваш процессор. Они обычно управляются планировщиком, который является стандартной частью любой операционной системы.

Чтобы создать поток, сначала должен быть запущен процесс. Затем, процесс создает поток, который выполняется, это может длится короткий или длительный период времени, в зависимости от процесса. Независимо от того, сколько времени будет выполнятся та или иная задача, создается впечатление, что ваш компьютер делает много вещей одновременно.

Каждый процесс имеет по крайней мере один поток, но нет максимального количества потоков, которое процесс может использовать. Для специализированных задач, чем больше у вас потоков, тем выше производительность вашего компьютера. С несколькими потоками один процесс может одновременно обрабатывать различные задачи.

Вы также услышите, как люди используют такие термины, как «многопоточность» и «гиперпоточность». Технология Hyper-Threading позволяет одному ядру ЦП выступать в качестве двух ядер, ускоряя выполнение конкретной программы или приложения.

Даже с одним ядром он может имитировать производительность, как если бы у вас было два ядра. Чем больше в процессоре ядер, тем больше потоков. Чем больше у вас потоков, тем выше будет производительность вашей системы.

Что такое Hyper-Threading

Гиперпоточность дебютировала в 2002 году и была попыткой Intel донести до пользователей параллельные вычисления. Это немного уловка, так как ОС распознает потоки как отдельные ядра процессора.Когда вы используете Intel Chip, ваш диспетчер задач покажет вам удвоенное количество ядер и обработает их как таковые. Это позволяет им обмениваться информацией и ускорять процесс декодирования, разделяя ресурсы между ядрами. Intel утверждает, что эта технология может повысить производительность до 30%.

Как работают процессорные ядра и потоки?

Ядра процессора являются аппаратными. Они делают всю тяжелую работу. Потоки используются, чтобы помочь процессору более эффективно выполнять множество паралельных задач одновременно. Если у ЦП нет гиперпоточности или многопоточности, задачи будут планироваться менее эффективно, что заставит его больше работать, чтобы получить доступ к информации, которая важна для запуска определенных приложений.

Одно ядро может работать над одной задачей за раз. Множество ядер помогут вам запускать различные приложения более плавно. Например, если вы планируете запускать видеоигру, для ее запуска потребуется несколько ядер, в то время как другие ядра могут запускать фоновые приложения, такие как Skype, Spotify, Chrome или что-то еще. Многопоточность только делает обработку более эффективной. Это, конечно, приведет к повышению производительности, но также заставит процессор потреблять больше энергии, но так как, многопоточность уже включена в микросхемах, так что это не повод для беспокойства. Хотя процессор потребляет больше энергии, это редко вызывает повышение температуры.

Короче говоря, когда вы рассматриваете возможность обновления, большее количество потоков означает большую производительность или лучшую многозадачность, в зависимости от того, какие приложения вы используете. Если вы используете несколько программ одновременно, это определенно приведет к повышению производительности.

Многоядерность

Первоначально процессоры имели одно ядро. Это означало, что на физическом процессоре был один центральный процессор. Для повышения производительности, процессоры заменяют на модели с большим количеством «ядер», или добавляют дополнительные центральные процессоры, если такая возможность предусмотренна производителем. Двухъядерный процессор имеет два центральных процессора, поэтому он представляется операционной системе как два процессора. Например, процессор с двумя ядрами может запускать два разных процесса одновременно. Это ускоряет вашу систему, потому что ваш компьютер может делать несколько вещей одновременно.

В отличие от многопоточности, здесь нет хитростей — двухъядерный ЦП буквально имеет два центральных процессора на чипе ЦП. Четырехъядерный процессор имеет четыре центральных процессора, восьмиъядерный процессор имеет восемь центральных процессоров и так далее.

Это помогает значительно повысить производительность, сохраняя при этом небольшой размер физического ЦП, чтобы он умещался в одном разъеме. Должен быть только один разъем ЦП с одним модулем ЦП, а не четыре различных разъема ЦП с четырьмя различными ЦП, каждый из которых требует собственного питания, охлаждения и другого аппаратного обеспечения. Время задержки меньше, потому что ядра могут обмениваться данными быстрее, поскольку все они находятся на одном чипе.

Диспетчер задач Windows показывает это наглядно. Здесь, например, вы можете видеть, что эта система имеет один фактический процессор (сокет) и четыре ядра. Многопоточность делает каждое ядро похожим на два ЦП для операционной системы, поэтому оно показывает 8 логических процессоров.

Выводы

В основном, больше ядер и больше потоков всегда будут означать лучшую производительность. Некоторые ориентированные на производительность программы, такие как редактирование видео, получат больше преимуществ от нескольких потоков.

Если ваша рабочая нагрузка включает в себя интенсивные задачи, такие как: работа с нагруженными базами данных, аналитическик задачами, редактированием видео, то многопоточные процессоры являются обязательными для вас. И Intel, и AMD предоставляют множество многоядерных, многопоточных процессоров, как для рабочих станций, так и для серверов малых и больших предприятий.

Threads в процессоре что это

Ответ на очередной из вопросов конкурса #msplatforma, проводимый в Твиттере Гайдаром Магдануровым
Вопрос звучал так: чем отличается Process от Thread?

Многопоточное программирование прикольная тема.
Сейчас, когда многоядерные процессоры едва ли не в каждом компьютере нормально писать многопоточные программы — это плюс, особенно для тех кто занимается «кровавым энтерпрайзом» (привет belnetmon) ‘у 🙂 )

Первое, что надо сказать – процесс состоит хотя бы из одного потока. В ОС каждому процессу соответствует адресное пространство и один управляющий поток. Собсвенно это и «задает» процесс.

С другой стороны, процесс можно рассматривать как поток исполняемых команд или просто поток. У потока есть счетчик команд, отслеживающий порядок выполнения действий. У него есть регистры, в которых хранятся текущие переменные. У него есть стек, содержащий протокол выполнения процесса, где на каждую процедуру, вызванную, но еще не вернувшуюся, отведен отдельный фрейм. Хотя поток должен исполняться внутри процесса, следует различать концепции потока и процесса. Процессы используются для группирования ресурсов, а потоки являются объектами, поочередно исполняющимися на центральном процессоре.

Концепция потоков добавляет к модели процесса возможность одновременного выполнения в одной и той же среде процесса нескольких программ, в достаточной степени независимых. Несколько потоков, работающих параллельно в одном процессе, аналогичны нескольким процессам, идущим параллельно на одном компьютере. В первом случае потоки разделяют адресное пространство, открытые файлы и другие ресурсы. Во втором случае процессы совместно пользуются памятью, накопителями, принтерами и другими ресурсами. Потоки обладают некоторыми свойствами процессов.

Любой поток состоит из двух компонентов:
— объекта ядра, через который операционная система управляет потоком. Там же хранится статистическая информация о потоке(дополнительные потоки создаются также ядром);
— стека потока, который содержит параметры всех функций и локальные переменные, необходимые потоку для выполнения кода.

Если подытожить все что сказано (и недосказанно тоже) выше в виде тезисов:
1. Поток определяет последовательность исполнения кода в процессе.
2. Процесс ничего не исполняет, он просто служит контейнером потоков.
3. Потоки всегда создаются в контексте какого-либо процесса, и вся их жизнь проходит только в его границах.
4. Потоки могут исполнять один и тот же код и манипулировать одними и теми же данными, а также совместно использовать описатели объектов ядра, поскольку таблица описателей создается не в отдельных потоках, а в процессах.
5. Так как потоки расходуют существенно меньше ресурсов, чем процессы, в процессе выполнения работы выгоднее создавать дополнительные потоки и избегать создания новых процессов.

В общем получается, что главное отличие процессов от потоков, состоит в том, что процессы изолированы друг от друга, так используют разные адресные пространства, а потоки, могут использовать одно и то же пространство (внутри процесса) при этом, выполняя действия не мешаяя друг другу.

P.S. В процессе написания этого поста консультировался со своей памятью, MSDN’ом и Bing’ом 🙂

Вы отправили слишком много запросов, поэтому ваш компьютер был заблокирован.

Для того, чтобы предотвратить автоматическое считывание информации с нашего сервиса, на Linguee допустимо лишь ограниченное количество запросов на каждого пользователя.
Пользователям, браузер которых поддерживает Javascript, доступно большее количество запросов, в отличие от пользователей, чей браузер не поддерживает Javascript. Попробуйте активировать Javascript в настройках вашего браузера, подождать несколько часов и снова воспользоваться нашим сервером.
Если же ваш компьютер является частью сети компьютеров, в которой большое количество пользователей одновременно пользуется Linguee,сообщитеоб этом нам.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *