#如果多个线程共同修改某个数据,就可能出现不可预料的结果。为了保证数据的正确性,需要对多个线程进行同步。
#使用Thread对象的Lock和RLock可以实现简单的线程同步,这两个对象都有acquire方法和release方法。对于每次只允许一个线程操作的数据,可以将操作放到acquire和release方法之间。
#多线程的优势在于可以同时运行多个任务,但当线程需要共享数据时,可能存在数据不同步的问题。
#考虑这样一个情况:一个列表里所有元素都是0,线程set从后向前改为1,而线程print负责从前往后读取列表并输出。
#线程set开始改的时候,线程print可能就来输出列表了,输出就成了一半0一半1,这就是数据不同步的问题。为了避免这个情况,引入了锁的概念。
#锁有两种状态:锁定和未锁定。当一个线程(如set)要访问共享数据时,必须先获得锁定;如果已经有别的线程(如print)获得锁定了,就让线程set暂停,也就是同步阻塞;等到线程print访问完毕,释放锁以后,再让线程set继续。
#经过这样的处理,输出列表要么全部输出0,要么全部输出1,不会再出现一半0一半1。
#实例代码如下:
1 #!/usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #线程同步 4 5 import threading 6 from time import sleep 7 from datetime import datetime 8 9 date_time_format='%y-%M-%d %H:%M:%S' 10 11 class MyThread(threading.Thread): 12 def __init__(self,threadID,name,counter): 13 threading.Thread.__init__(self) 14 self.threadID=threadID 15 self.name=name 16 self.counter=counter 17 18 def run(self): 19 print('开启线程:'+self.name) 20 #获取锁,用于线程同步 21 threadLock.acquire() 22 print_time(self.name,self.counter,3) 23 #释放锁,开启下一个线程 24 threadLock.release() 25 26 def date_time_str(date_time): 27 return datetime.strftime(date_time,date_time_format) 28 29 def print_time(threadName,delay,counter): 30 while counter: 31 sleep(delay) 32 print('%s:%s'%(threadName,date_time_str(datetime.now()))) 33 counter-=1 34 35 def main(): 36 thread1=MyThread(1,'Thread-1',1) 37 thread2=MyThread(2,'Thread-2',2) 38 39 #开启新线程 40 thread1.start() 41 thread2.start() 42 43 #添加线程到线程列表 44 threads.append(thread1) 45 threads.append(thread2) 46 47 #等待所有线程完成 48 for t in threads: 49 t.join() 50 print('退出主线程') 51 52 if __name__=='__main__': 53 threadLock=threading.Lock() 54 threads=[] 55 main()
#执行结果如下:
1 D:Pythonworkspace>python 线程同步.py 2 开启线程:Thread-1 3 开启线程:Thread-2 4 Thread-1:18-22-30 17:22:36 5 Thread-1:18-22-30 17:22:37 6 Thread-1:18-22-30 17:22:38 7 Thread-2:18-22-30 17:22:40 8 Thread-2:18-22-30 17:22:42 9 Thread-2:18-22-30 17:22:44 10 退出主线程
#由执行结果看到,程序正确得到了同步效果。