この記事では、Python のマルチスレッドについて詳しく紹介 (コード例) しています。一定の参考価値があります。必要な友人は参考にしてください。お役に立てれば幸いです。
この記事では、Python の学習中に遭遇する問題といくつかの一般的な使用法を記録します。この開発環境の Python バージョンは 2.7 であることに注意してください。
1. Python ファイルの名前付け
Python ファイルに名前を付けるときは、システムのデフォルトのモジュール名と競合しないように注意する必要があり、競合しないとエラーが報告されます。
次の例に示すように、スレッドを学習する場合、ファイル名は threading.py
ですが、Python スクリプトはまったく正常で問題ありません。その結果、次のエラーが報告されます。 AttributeError: 'module' オブジェクトには属性 'xxx'
がありません。
threading.py
# -*- coding:utf-8 -*- """ @author: Corwien @file: threading_test.py @time: 18/8/25 09:14 """ import threading # 获取已激活的线程数 print(threading.active_count())
実行:
➜ baseLearn python threading/threading.py Traceback (most recent call last): File "threading/threading.py", line 9, in <module> import threading File "/Users/kaiyiwang/Code/python/baseLearn/threading/threading.py", line 12, in <module> print(threading.active_count()) AttributeError: 'module' object has no attribute 'active_count' ➜ baseLearn</module></module>
問題の場所:
View import
ライブラリ ソースファイルを調べたところ、ソース ファイルが存在し、エラーがないことがわかりました。また、ソース ファイルの .pyc
ファイルも存在します。
問題解決策:
1.py スクリプトに名前を付けるときは、Python の予約語やモジュール名などと同じ単語を使用しないでください。
-
#2.
threading_test.pyを削除します。ライブラリの .pyc
ファイル (py であるため、スクリプトは実行されるたびに .pyc ファイルを生成します。.pyc ファイルが生成されている場合でも、コードが更新されていなければ、実行時に pyc が引き続き使用されます。そのため、.pyc ファイルを削除して)、コードを再実行するか、コードが実行されている環境で、現在のマシンの .pyc ファイルをコピーして置き換えることができるプログラムを見つけます。 #スクリプト ファイル名を に変更して実行しても、エラーは報告されません。
➜ baseLearn python threading/threading_test.py 1 ➜ baseLearn
2. マルチスレッド スレッドマルチスレッドは、プログラムの計算を高速化する効果的な方法です。Python のマルチスレッド モジュール
は、すばやく簡単に入手できます。このセクションから始めましょう。みんなの使い方。
1. thread を追加
# -*- coding:utf-8 -*- """ @author: Corwien @file: threading_test.py @time: 18/8/25 09:14 """ import threading # 获取已激活的线程数 # print(threading.active_count()) # 查看所有线程信息 # print(threading.enumerate()) # 查看现在正在运行的线程 # print(threading.current_thread()) def thread_job(): print('This is a thread of %s' % threading.current_thread()) def main(): thread = threading.Thread(target=thread_job,) # 定义线程 thread.start() # 让线程开始工作 if __name__ == '__main__': main()
2. Join 関数join() を追加しなかった結果
によりスレッド作業にかかる時間を増加させます
threading_join.py
# -*- coding:utf-8 -*- """ @author: Corwien @file: threading_join.py @time: 18/8/25 09:14 """ import threading import time def thread_job(): print('T1 start\n') for i in range(10): time.sleep(0.1) # 任务时间0.1s print("T1 finish\n") def main(): added_thread = threading.Thread(target=thread_job, name='T1') # 定义线程 added_thread.start() # 让线程开始工作 print("all done\n") if __name__ == '__main__': main()
期待される出力結果は次のとおりです。 order 順番に実行します: <pre class="brush:php;toolbar:false">T1 start
T1 finish
all done</pre>
ただし、実際の実行結果は次のとおりです:
➜ baseLearn python threading/threading_join.py T1 start all done T1 finish ➜ baseLearn
join() の結果
スレッド タスクは完了する前に出力されます
すべて完了# ##。順序に従いたい場合は、スレッドを開始した後にスレッドでjoin
を呼び出すことができます:added_thread.start() added_thread.join() print("all done\n")
印刷結果:
➜ baseLearn python threading/threading_join.py T1 start T1 finish all done
完全なスクリプト ファイル:
# -*- coding:utf-8 -*- """ @author: Corwien @file: threading_join.py @time: 18/8/25 09:14 """ import threading import time def thread_job(): print('T1 start\n') for i in range(10): time.sleep(0.1) # 任务时间0.1s print("T1 finish\n") def main(): added_thread = threading.Thread(target=thread_job, name='T1') # 定义线程 added_thread.start() # 让线程开始工作 added_thread.join() print("all done\n") if __name__ == '__main__': main()small スキルをテストしてください2 つのスレッドを追加すると、どのような出力が出力されますか?
# -*- coding:utf-8 -*- """ @author: Corwien @file: threading_join.py @time: 18/8/25 09:14 """ import threading import time def T1_job(): print('T1 start\n') for i in range(10): time.sleep(0.1) # 任务时间0.1s print("T1 finish\n") def T2_job(): print("T2 start\n") print("T2 finish\n") def main(): thread_1 = threading.Thread(target=T1_job, name='T1') # 定义线程 thread_2 = threading.Thread(target=T2_job, name='T2') # 定义线程 thread_1.start() # 开启T1 thread_2.start() # 开启T2 print("all done\n") if __name__ == '__main__': main()「1 つ」の結果出力は次のとおりです:
T1 start
T2 start
T2 finish
all done
T1 finish
現在、T1 も T2 も join
を持っていません。ここで「1 つ」と言っているのは、すべてのものが出現しているためです。完了 2 つのスレッドの実行速度に完全に依存し、すべてが完了した後に T2 終了が表示される可能性は十分にあります。このような厄介な実行方法を許容することはできないため、join を使用して制御する必要があります。 T1 の開始後、T2 の開始前にthread_1.join() を追加してみましょう。 :
thread_1.start() thread_1.join() # notice the difference! thread_2.start() print("all done\n")印刷結果:
T1 start T1 finish T2 start all done T2 finish
が表示されます。 T2 は、T1 が終了するのを待ってから実行を開始します。
3. 処理結果を保存するキュー実装関数コードは関数を実装し、データ リスト内のデータを転送し、4 つのスレッドを使用して処理し、保存します。 Queue 内の結果、スレッドの実行後、Queue から保存された結果を取得します。 マルチスレッド関数で Queue
を定義して戻り値を保存します。は置き換えられます。 return
、マルチスレッド リストを定義し、処理用の多次元データ リストを初期化します:threading_queue.py
# -*- coding:utf-8 -*- """ @author: Corwien @file: threading_queue.py @time: 18/8/25 09:14 """ import threading import time from queue import Queue def job(l, q): for i in range(len(l)): l[i] = l[i] ** 2 q.put(l) #多线程调用的函数不能用return返回值 def multithreading(): q = Queue() #q中存放返回值,代替return的返回值 threads = [] data = [[1,2,3],[3,4,5],[4,4,4],[5,5,5]] for i in range(4): #定义四个线程 t = threading.Thread(target=job, args=(data[i], q)) #Thread首字母要大写,被调用的job函数没有括号,只是一个索引,参数在后面 t.start() #开始线程 threads.append(t) #把每个线程append到线程列表中 for thread in threads: thread.join() results = [] for _ in range(4): results.append(q.get()) #q.get()按顺序从q中拿出一个值 print(results) if __name__ == '__main__': multithreading()上記のスクリプトを実行すると、エラーが発生しました:
➜ baseLearn python threading/threading_queue.py Traceback (most recent call last): File "threading/threading_queue.py", line 11, in <module> from queue import Queue ImportError: No module named queue</module>
理由を確認したところ、Python のバージョンが原因でした:
解決策: 'Queue' という名前のモジュールはありませんPython 2 では、モジュールの名前は Queue です, Python 3 では、PEP8 ガイドライン (モジュール名はすべて小文字) に従うように名前が変更され、キューになりました。クラスはすべてのバージョンで (PEP8 に従って) Queue のままです。
通常、次のように記述します。バージョンのポータブルインポートは次のようになります:
try: import queue except ImportError: import Queue as queuepython2 では次のように引用できます:
from Queue import QueuePrint:
baseLearn python ./threading/threading_queue.py [[1, 4, 9], [9, 16, 25], [16, 16, 16], [25, 25, 25]]完全なコード:
threading_queue.py
# -*- coding:utf-8 -*- """ @author: Corwien @file: threading_queue.py @time: 18/8/25 09:14 """ import threading # import time from Queue import Queue def job(l, q): for i in range(len(l)): l[i] = l[i] ** 2 q.put(l) #多线程调用的函数不能用return返回值 def multithreading(): q = Queue() #q中存放返回值,代替return的返回值 threads = [] data = [[1,2,3],[3,4,5],[4,4,4],[5,5,5]] for i in range(4): #定义四个线程 t = threading.Thread(target=job, args=(data[i], q)) #Thread首字母要大写,被调用的job函数没有括号,只是一个索引,参数在后面 t.start() #开始线程 threads.append(t) #把每个线程append到线程列表中 for thread in threads: thread.join() results = [] for _ in range(4): results.append(q.get()) #q.get()按顺序从q中拿出一个值 print(results) if __name__ == '__main__': multithreading()
4. GIL 効率の問題GIL とは何ですか?
グローバル インタプリタ ロック (ギル)
。このことにより、Python は一度に 1 つの処理のみを行うことができます。 GILの説明:尽管Python完全支持多线程编程, 但是解释器的C语言实现部分在完全并行执行时并不是线程安全的。 实际上,解释器被一个全局解释器锁保护着,它确保任何时候都只有一个Python线程执行。 GIL最大的问题就是Python的多线程程序并不能利用多核CPU的优势 (比如一个使用了多个线程的计算密集型程序只会在一个单CPU上面运行)。在讨论普通的GIL之前,有一点要强调的是GIL只会影响到那些严重依赖CPU的程序(比如计算型的)。 如果你的程序大部分只会涉及到I/O,比如网络交互,那么使用多线程就很合适, 因为它们大部分时间都在等待。实际上,你完全可以放心的创建几千个Python线程, 现代操作系统运行这么多线程没有任何压力,没啥可担心的。
测试GIL
我们创建一个 job
, 分别用 threading 和 一般的方式执行这段程序. 并且创建一个 list 来存放我们要处理的数据. 在 Normal 的时候, 我们这个 list 扩展4倍, 在 threading 的时候, 我们建立4个线程, 并对运行时间进行对比.
threading_gil.py
# -*- coding:utf-8 -*- """ @author: Corwien @file: threading_gil.py @time: 18/8/25 09:14 """ import threading from Queue import Queue import copy import time def job(l, q): res = sum(l) q.put(l) #多线程调用的函数不能用return返回值 def multithreading(l): q = Queue() #q中存放返回值,代替return的返回值 threads = [] for i in range(4): #定义四个线程 t = threading.Thread(target=job, args=(copy.copy(l), q), name="T%i" % i) #Thread首字母要大写,被调用的job函数没有括号,只是一个索引,参数在后面 t.start() #开始线程 threads.append(t) #把每个线程append到线程列表中 [t.join() for t in threads] total = 0 for _ in range(4): total = q.get() #q.get()按顺序从q中拿出一个值 print(total) def normal(l): total = sum(l) print(total) if __name__ == '__main__': l = list(range(1000000)) s_t = time.time() normal(l*4) print('normal:', time.time() - s_t) s_t = time.time() multithreading(l) print('multithreading: ', time.time() - s_t)
如果你成功运行整套程序, 你大概会有这样的输出. 我们的运算结果没错, 所以程序 threading 和 Normal 运行了一样多次的运算. 但是我们发现 threading 却没有快多少, 按理来说, 我们预期会要快3-4倍, 因为有建立4个线程, 但是并没有. 这就是其中的 GIL 在作怪.
1999998000000 normal: 0.10034608840942383 1999998000000 multithreading: 0.08421492576599121
5、线程锁Lock
不使用 Lock 的情况
threading_lock.py
# -*- coding:utf-8 -*- """ @author: Corwien @file: threading_lock.py @time: 18/8/25 09:14 """ import threading # 全局变量A的值每次加1,循环10次,并打印 def job1(): global A for i in range(10): A+=1 print('job1',A) # 全局变量A的值每次加10,循环10次,并打印 def job2(): global A for i in range(10): A+=10 print('job2',A) # 定义两个线程,分别执行函数一和函数二 if __name__== '__main__': A=0 t1=threading.Thread(target=job1) t2=threading.Thread(target=job2) t1.start() t2.start() t1.join() t2.join()
打印输出数据:
➜ baseLearn python ./threading/threading_lock.py ('job1', ('job2'1) , (11)'job1' ('job2', 22) ('job2', 32) ('job2', 42) ('job2', 52) ('job2', 62) ('job2', 72) ('job2', 82) ('job2', 92) ('job2', 102) , 12) ('job1', 103) ('job1', 104) ('job1', 105) ('job1', 106) ('job1', 107) ('job1', 108) ('job1', 109) ('job1', 110)
可以看出,打印的结果非常混乱
使用 Lock 的情况
lock在不同线程使用同一共享内存
时,能够确保线程之间互不影响,使用lock的方法是, 在每个线程执行运算修改共享内存之前,执行lock.acquire()
将共享内存上锁, 确保当前线程执行时,内存不会被其他线程访问,执行运算完毕后,使用lock.release()
将锁打开, 保证其他的线程可以使用该共享内存。
函数一和函数二加锁
def job1(): global A,lock lock.acquire() for i in range(10): A+=1 print('job1',A) lock.release() def job2(): global A,lock lock.acquire() for i in range(10): A+=10 print('job2',A) lock.release()
主函数中定义一个Lock
if __name__== '__main__': lock=threading.Lock() A=0 t1=threading.Thread(target=job1) t2=threading.Thread(target=job2) t1.start() t2.start() t1.join() t2.join()
完整代码:
# -*- coding:utf-8 -*- """ @author: Corwien @file: threading_lock.py @time: 18/8/25 09:14 """ import threading def job1(): global A,lock lock.acquire() for i in range(10): A+=1 print('job1',A) lock.release() def job2(): global A,lock lock.acquire() for i in range(10): A+=10 print('job2',A) lock.release() if __name__== '__main__': lock = threading.Lock() A=0 t1=threading.Thread(target=job1) t2=threading.Thread(target=job2) t1.start() t2.start() t1.join() t2.join()
打印输出:
➜ baseLearn python ./threading/threading_lock.py ('job1', 1) ('job1', 2) ('job1', 3) ('job1', 4) ('job1', 5) ('job1', 6) ('job1', 7) ('job1', 8) ('job1', 9) ('job1', 10) ('job2', 20) ('job2', 30) ('job2', 40) ('job2', 50) ('job2', 60) ('job2', 70) ('job2', 80) ('job2', 90) ('job2', 100) ('job2', 110)
从打印结果来看,使用lock
后,一个一个线程执行完。使用lock
和不使用lock,最后打印输出的结果是不同的。
相关推荐:
以上がPython でのマルチスレッドの詳細な紹介 (コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

限られた時間でPythonの学習効率を最大化するには、PythonのDateTime、時間、およびスケジュールモジュールを使用できます。 1. DateTimeモジュールは、学習時間を記録および計画するために使用されます。 2。時間モジュールは、勉強と休息の時間を設定するのに役立ちます。 3.スケジュールモジュールは、毎週の学習タスクを自動的に配置します。

PythonはゲームとGUI開発に優れています。 1)ゲーム開発は、2Dゲームの作成に適した図面、オーディオ、その他の機能を提供し、Pygameを使用します。 2)GUI開発は、TKINTERまたはPYQTを選択できます。 TKINTERはシンプルで使いやすく、PYQTは豊富な機能を備えており、専門能力開発に適しています。

Pythonは、データサイエンス、Web開発、自動化タスクに適していますが、Cはシステムプログラミング、ゲーム開発、組み込みシステムに適しています。 Pythonは、そのシンプルさと強力なエコシステムで知られていますが、Cは高性能および基礎となる制御機能で知られています。

2時間以内にPythonの基本的なプログラミングの概念とスキルを学ぶことができます。 1.変数とデータ型、2。マスターコントロールフロー(条件付きステートメントとループ)、3。機能の定義と使用を理解する4。

Pythonは、Web開発、データサイエンス、機械学習、自動化、スクリプトの分野で広く使用されています。 1)Web開発では、DjangoおよびFlask Frameworksが開発プロセスを簡素化します。 2)データサイエンスと機械学習の分野では、Numpy、Pandas、Scikit-Learn、Tensorflowライブラリが強力なサポートを提供します。 3)自動化とスクリプトの観点から、Pythonは自動テストやシステム管理などのタスクに適しています。

2時間以内にPythonの基本を学ぶことができます。 1。変数とデータ型を学習します。2。ステートメントやループの場合などのマスター制御構造、3。関数の定義と使用を理解します。これらは、簡単なPythonプログラムの作成を開始するのに役立ちます。

10時間以内にコンピューター初心者プログラミングの基本を教える方法は?コンピューター初心者にプログラミングの知識を教えるのに10時間しかない場合、何を教えることを選びますか...

fiddlereveryversings for the-middleの測定値を使用するときに検出されないようにする方法


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

SecLists
SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)
