Python でのスレッドの使用例と、スレッドの競合を回避する方法をいくつか見ていきます。
次の例を複数回実行して、スレッドが予測不可能であること、およびスレッドが実行されるたびに異なる結果を生成することを確認できるようにする必要があります。免責事項: GIL についてこれ以降聞いたことは忘れてください。GIL は私が示そうとしているものには影響しません。
5 つの異なる URL をリクエストします:
シングルスレッド
import time import urllib2 def get_responses(): urls = [ 'http://www.google.com', 'http://www.amazon.com', 'http://www.ebay.com', 'http://www.alibaba.com', 'http://www.reddit.com' ] start = time.time() for url in urls: print url resp = urllib2.urlopen(url) print resp.getcode() print "Elapsed time: %s" % (time.time()-start) get_responses()
出力は次のとおりです:
http://www.google.com 200 http://www.amazon.com 200 http://www.ebay.com 200 http://www.alibaba.com 200 http://www.reddit.com 200 Elapsed time: 3.0814409256
説明:
URLは順番にリクエストされます
CPU は、1 つの URL から応答を取得しない限り、次の URL をリクエストしません
ネットワーク リクエストには時間がかかるため、CPU はネットワーク リクエストが返されるまでアイドル状態になります。
マルチスレッド
import urllib2 import time from threading import Thread class GetUrlThread(Thread): def __init__(self, url): self.url = url super(GetUrlThread, self).__init__() def run(self): resp = urllib2.urlopen(self.url) print self.url, resp.getcode() def get_responses(): urls = [ 'http://www.google.com', 'http://www.amazon.com', 'http://www.ebay.com', 'http://www.alibaba.com', 'http://www.reddit.com' ] start = time.time() threads = [] for url in urls: t = GetUrlThread(url) threads.append(t) t.start() for t in threads: t.join() print "Elapsed time: %s" % (time.time()-start) get_responses()
出力:
http://www.reddit.com 200 http://www.google.com 200 http://www.amazon.com 200 http://www.alibaba.com 200 http://www.ebay.com 200 Elapsed time: 0.689890861511
説明:
プログラム実行時間の向上を実現
CPU の待ち時間を短縮するために、マルチスレッド プログラムを作成しました。あるスレッドのネットワーク リクエストが返されるのを待っているときに、CPU は他のスレッドに切り替えて、他のスレッドでネットワーク リクエストを行うことができます。
スレッドが URL を処理することを期待しているため、スレッド クラスをインスタンス化するときに URL を渡します。
スレッドの実行とは、クラス内の run()
メソッドを実行することを意味します。
何を望んでも、各スレッドは実行する必要があります run()
。
URL ごとにスレッドを作成し、start()
メソッドを呼び出します。これにより、スレッド内で start()
方法,这告诉了cpu可以执行线程中的run()
メソッドを実行するように CPU に指示されます。
すべてのスレッドの実行が完了するまでの時間を計算したいので、join()
メソッドを呼び出します。
join()
次の命令を実行する前に、このスレッドが終了するまで待機するようにメインスレッドに通知できます。
各スレッドに対して join()
メソッドを呼び出すため、すべてのスレッドの実行が完了した後に実行時間を計算します。
スレッドについて:
CPU は、start()
を呼び出した直後に start()
后马上执行run()
メソッドを実行しない場合があります。
異なるスレッド間の実行順序を決定することはできません。 run()
メソッド内のステートメントが順番に実行されることが保証されます。 run()
りー
このプログラムを複数回実行すると、さまざまな結果が表示されます。 説明:で。 some_var
是15
的时候,线程t1
读取了some_var
,这个时刻cpu将控制权给了另一个线程t2
t2
线程读到的some_var
也是15
t1
和t2
都把some_var
加到16
t1
t2
两个线程使some_var + 2
变成17
よりも低くなる可能性があります。 50
from threading import Thread #define a global variable some_var = 0 class IncrementThread(Thread): def run(self): #we want to read a global variable #and then increment it global some_var read_value = some_var print "some_var in %s is %d" % (self.name, read_value) some_var = read_value + 1 print "some_var in %s after increment is %d" % (self.name, some_var) def use_increment_thread(): threads = [] for i in range(50): t = IncrementThread() threads.append(t) t.start() for t in threads: t.join() print "After 50 modifications, some_var should have become 50" print "After 50 modifications, some_var is %d" % (some_var,) use_increment_thread()
がロックを解放した場合、同じ操作は実行されません t1
获得了锁。其他的线程在t1
我们想要确定的是一旦线程t1
已经读取了some_var
,直到t1
完成了修改some_var
,其他的线程才可以读取some_var
这样读取和修改some_var
成了逻辑上的原子操作。
让我们用一个例子来证明一个线程不能影响其他线程内的变量(非全局变量)。
time.sleep()可以使一个线程挂起,强制线程切换发生。
from threading import Thread import time class CreateListThread(Thread): def run(self): self.entries = [] for i in range(10): time.sleep(1) self.entries.append(i) print self.entries def use_create_list_thread(): for i in range(3): t = CreateListThread() t.start() use_create_list_thread()
运行几次后发现并没有打印出争取的结果。当一个线程正在打印的时候,cpu切换到了另一个线程,所以产生了不正确的结果。我们需要确保print self.entries
是个逻辑上的原子操作,以防打印时被其他线程打断。
我们使用了Lock(),来看下边的例子。
from threading import Thread, Lock import time lock = Lock() class CreateListThread(Thread): def run(self): self.entries = [] for i in range(10): time.sleep(1) self.entries.append(i) lock.acquire() print self.entries lock.release() def use_create_list_thread(): for i in range(3): t = CreateListThread() t.start() use_create_list_thread()
这次我们看到了正确的结果。证明了一个线程不可以修改其他线程内部的变量(非全局变量)。
原文出处: Akshar Raaj
以上がPython のスレッドを理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。