如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。
一、(1)未采用锁,线程1与线程2并行执行。
import threading from time import sleep,ctime class MyThread(threading.Thread): def __init__(self, func, arg): super(MyThread, self).__init__() self.func = func self.arg = arg # 重写run()方法 def run(self): """ threadLock.acquire() #获取锁,用于线程同步 """ self.func(self.arg) """ threadLock.release()#释放锁,开启下一个线程 """ def f(n): for i in range(n): sleep(1) print(i,threading.current_thread().name,ctime()) """ threadLock = threading.Lock() """ for i in range(2): thread = MyThread(f,5) thread.start()
输出如下:
00 Thread-1Thread-2 Mon Oct 26 19:52:12 2020Mon Oct 26 19:52:12 2020
11 Thread-1 Thread-2Mon Oct 26 19:52:13 2020
Mon Oct 26 19:52:13 2020
22 Thread-1Thread-2 Mon Oct 26 19:52:14 2020Mon Oct 26 19:52:14 2020
33 Thread-1Thread-2 Mon Oct 26 19:52:15 2020Mon Oct 26 19:52:15 2020
44 Thread-2Thread-1 Mon Oct 26 19:52:16 2020Mon Oct 26 19:52:16 2020
(2)采用锁,先执行线程1,后执行线程2.
import threading from time import sleep,ctime class MyThread(threading.Thread): def __init__(self, func, arg): super(MyThread, self).__init__() self.func = func self.arg = arg # 重写run()方法 def run(self): threadLock.acquire() #获取锁,用于线程同步 self.func(self.arg) threadLock.release()#释放锁,开启下一个线程 def f(n): for i in range(n): sleep(1) print(i,threading.current_thread().name,ctime()) threadLock = threading.Lock() for i in range(2): thread = MyThread(f,5) thread.start()
输出如下:
0 Thread-1 Mon Oct 26 19:59:17 2020
1 Thread-1 Mon Oct 26 19:59:18 2020
2 Thread-1 Mon Oct 26 19:59:19 2020
3 Thread-1 Mon Oct 26 19:59:20 2020
4 Thread-1 Mon Oct 26 19:59:21 2020
0 Thread-2 Mon Oct 26 19:59:22 2020
1 Thread-2 Mon Oct 26 19:59:23 2020
2 Thread-2 Mon Oct 26 19:59:24 2020
3 Thread-2 Mon Oct 26 19:59:25 2020
4 Thread-2 Mon Oct 26 19:59:26 2020
应用所阻塞子线程的执行,应用join阻塞主线程的执行。
import threading from time import sleep,ctime class MyThread(threading.Thread): def __init__(self, func, arg): super(MyThread, self).__init__() self.func = func self.arg = arg # 重写run()方法 def run(self): threadLock.acquire() #获取锁,用于线程同步 self.func(self.arg) threadLock.release()#释放锁,开启下一个线程 number=0 def f(n): global number for i in range(n): number+=1 print(number,threading.current_thread().name,ctime()) threadLock = threading.Lock() threads=[] for i in range(10): thread = MyThread(f,10) threads.append(thread) for t in threads: t.start() t.join() print(number,threading.current_thread().name,ctime())
输出如下:
10 Thread-1 Mon Oct 26 20:09:59 2020 20 Thread-2 Mon Oct 26 20:09:59 2020 30 Thread-3 Mon Oct 26 20:09:59 2020 40 Thread-4 Mon Oct 26 20:09:59 2020 50 Thread-5 Mon Oct 26 20:09:59 2020 60 Thread-6 Mon Oct 26 20:09:59 2020 70 Thread-7 Mon Oct 26 20:09:59 2020 80 Thread-8 Mon Oct 26 20:09:59 2020 90 Thread-9 Mon Oct 26 20:09:59 2020 100 Thread-10 Mon Oct 26 20:09:59 2020 100 MainThread Mon Oct 26 20:09:59 2020