2016-08-26 12 views
1

У меня есть следующий код:Python Многопоточность основы спутанность

import time 
from threading import Thread 

def fun1(): 
time.sleep(5) 

def fun2(): 
time.sleep(5) 

def fun3(): 
time.sleep(5) 

def fun4(): 
time.sleep(5) 

if __name__ == '__main__': 
    t1 = Thread(target=fun1, args=()) 
    t2 = Thread(target=fun2, args=()) 
    t3 = Thread(target=fun3, args=()) 
    t4 = Thread(target=fun4, args=()) 
    t1.start() 
    t2.start() 
    t3.start() 
    t4.start() 
    start = time.clock() 
    t1.join() 
    t2.join() 
    t3.join() 
    t4.join() 
    end = time.clock() 
    print("Time Taken = ",end-start) 

Que1: В то время только один поток будет обслуживаемой, то есть, если элемент управления с резьбой t1, остальные другие потоки будут ждать. После переключения контекста в поток t2 останутся остальные потоки (t1, t3 и t4). Это правильное понимание?

Que2: Если мое понимание Que1 истинно, общее время (начало-конец) должно составлять двадцать секунд (как работает как последовательное, а не многопоточное) ... но оно несколько близко к 5 секундам .... почему? В конце дня потоки выполняются последовательно (хотя и не полностью) один за другим. Пожалуйста, объясните в условиях мирян. Где мое понимание неверно?

Que3: Что делать, если я делаю то же самое, используя многопроцессорность? Как будет выполняться выполнение?

Que4: Предположим (предположим) fun1() имеет код, который выполняет 1000 повторов счетчика ping для маршрутизатора 1 и занимает время 1 мин. Similary, fun2() выполняет 1000 повторов счетчика ping на маршрутизатор 2 и занимает время 1 мин. Similary, fun3() выполняет 1000 повторов счетчика ping на маршрутизатор 3 и занимает время 1 мин.

Если я делаю это последовательно, общее ожидаемое время составляет 3 минуты (пинг на R1, затем пинг на R2, а затем пинг на R3) Но когда я сделал это с помощью потоковой передачи, общее время выполнения было почти близко к 1 минимум Зачем ? Я не могу понять.

ответ

2

Q1: Да

Q2: Если нити каждый сделал то, что потребовалось 5 секунд времени обработки, то можно было бы ожидать общее время на 20 секунд. Но каждый поток просто спит в течение 5 секунд, поэтому каждый поток освобождает GIL и, таким образом, позволяет другим потокам запускаться «параллельно» (только концептуально), так как он ждет таймаута ожидания.

Q3: Многопроцессорность, в отличие от threads, создает дочерние процессы, которые могут выполняться на разных процессорах одновременно (фактически параллельно). Но даже если эти sleeps работают на отдельных процессорах, они все равно будут собираться в течение примерно 5 секунд. Если они будут работать на одном процессоре, механизм синхронизации времени ОС будет аналогичен механизму Threading Python, а также обеспечить их завершение через 5 минут.

Q4: Это та же концепция, что и у sleep. Каждый ping не является интенсивным с точки зрения ЦП, и поэтому его поток редко владеет GIL. Это позволяет концептуально запускать все три потока ping параллельно.

3

Блокировка вызовов в Python (sleep, ожидание ввода/вывода или блокировок) освобождает GIL, позволяя другим потокам запускаться во время их блокировки, поэтому все четыре потока могут sleep параллельно, вот почему вы видите пять вторая задержка. Если вы хотите увидеть эффекты конкуренции GIL, попросите функцию потока выполнить что-то, связанное с процессором, например.

def fun(): 
    for _ in xrange(1000000000): 
     pass 

multiprocessing не будет ничего менять в sleep случае, так как вы не GIL связаны, но это улучшило бы время настенных часов из процессора связана случае, если у вас есть более чем одно ядро ​​для запуска на ,

1

Для многопоточной среды в python.У нас есть два очень разных типа:

  • Цементирование: как добавление числа, выполнение цикла ... любые действия, которые потребляют процессор. В этой задаче выполняется GIL, чтобы предотвратить запуск другого потока.
  • Не связано с ЦП (может быть ожиданием операций ввода-вывода из внешнего ресурса, такого как сеть ...): системный вызов сна не использует процессор, поэтому он в этом виде. этот вид выпускает GIL, пока он ждет ввода-вывода, тайм-аут ожидания ... поэтому другой поток может занять блокировку и работу. Вот почему ваша программа занимает около 5 секунд, потому что все ваши потоки могут работать параллельно.