我们可以使用python提供的threading模块中的Thread通过继承来实现自己的线程类,在__init__中借用父类的构造函数实例化子类,可以在子类中重写Thread类中的run函数,来实现自己的逻辑,首先创建实例thread1 = MyThread(“1”, ""Thread1),当执行thread1.start()的时候会自动调用run函数来执行其中的代码
from threading import Thread
class MyThread(Thread):
def __init__(self, threadId, threadName):
Thread.__init__(self)
self.threadId = threadId
self.threadName = threadName
def run(self):
for i in range(5):
print(i + 1, self.threadId, self.threadName)
print("%s 结束" % self.threadName)
thread1 = MyThread("1", "Thread1")
thread2 = MyThread("2", "Thread2")
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("主线程结束")
输出
1 1 Thread1
1 2 Thread2
2 2 Thread2
3 2 Thread2
4 2 Thread2
5 2 Thread2
Thread2 结束
2 1 Thread1
3 1 Thread1
4 1 Thread1
5 1 Thread1
Thread1 结束
主线程结束
PS:线程在执行的时候会去使用cpu产生的时间片,由于是非阻塞的,时间片分配给哪个线程是随机的,因此输出结果可以看到在线程结束前,顺序都是乱序的,join()函数的作用是加入到当前主线程中,等到thread1,thread2都执行完以后才会结束主线程,否则主线程的执行也将是并行的,很可能提前结束
我们在不同的线程中使用同一个全局变量或者其他公共资源的时候,如果在另一个线程中对其有修改的操作,那么并不能保证当前线程中获取到的就是内部修改后的结果,可能已经被其他线程访问并修改了,于此,我们期望在当前线程中使用这个公共资源时不希望被其他线程访问修改时,可以对其上同步锁,以保证只有当某个线程访问完以后,其他线程才可以继续操作。
from threading import Thread
counter = 0
class MyThread(Thread):
def __init__(self, threadId, threadName):
Thread.__init__(self)
self.threadId = threadId
self.threadName = threadName
def count(self):
global counter
counter += 1
def showCount(self, i):
global counter
print("newcount%d %s" % (i+1, self.threadName + " " + str(counter)))
def run(self):
for i in range(5):
self.count()
print("precount%d %s" % (i+1, self.threadName + " " + str(counter)))
self.showCount(i)
print("%s 结束" % self.threadName)
thread1 = MyThread("1", "Thread1")
thread2 = MyThread("2", "Thread2")
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("主线程结束")
输出
precount1 Thread1 1
newcount1 Thread1 1
# 这一步Thread1在修改完count=2以后,由于线程是同步的,被Thread2访问并修改为了3。
# 当Thread1再次去访问这个全局变量counter的时候,拿到的是被Thread1修改后的结果3。
# 但期望的结果是2
precount2 Thread1 2
precount1 Thread2 3
newcount2 Thread1 3
precount3 Thread1 4
newcount3 Thread1 4
precount4 Thread1 5
newcount4 Thread1 5
precount5 Thread1 6
newcount5 Thread1 6
newcount1 Thread2 6
precount2 Thread2 7
newcount2 Thread2 7
precount3 Thread2 8
newcount3 Thread2 8
precount4 Thread2 9
newcount4 Thread2 9
precount5 Thread2 10
newcount5 Thread2 10
Thread2 结束
Thread1 结束
主线程结束
通过在count之前调用lock.acquire()上锁,可以防止其他线程争抢资源的访问,只有当锁我当前线程执行完showCount正确访问到我期望的结果以后,通过lock.release()释放同步锁,其他线程才能执行count和showCount。
from threading import Thread, Lock
lock = Lock()
counter = 0
class MyThread(Thread):
def __init__(self, threadId, threadName):
Thread.__init__(self)
self.threadId = threadId
self.threadName = threadName
def count(self):
global counter
counter += 1
def showCount(self, i):
global counter
print("newcount%d %s" % (i+1, self.threadName + " " + str(counter)))
def run(self):
for i in range(5):
lock.acquire()
self.count()
print("precount%d %s" % (i+1, self.threadName + " " + str(counter)))
self.showCount(i)
lock.release()
print("%s 结束" % self.threadName)
thread1 = MyThread("1", "Thread1")
thread2 = MyThread("2", "Thread2")
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("主线程结束")
输出
precount1 Thread1 1
newcount1 Thread1 1
precount2 Thread1 2
newcount2 Thread1 2
precount3 Thread1 3
newcount3 Thread1 3
precount4 Thread1 4
newcount4 Thread1 4
precount5 Thread1 5
newcount5 Thread1 5
Thread1 结束
precount1 Thread2 6
newcount1 Thread2 6
precount2 Thread2 7
newcount2 Thread2 7
precount3 Thread2 8
newcount3 Thread2 8
precount4 Thread2 9
newcount4 Thread2 9
precount5 Thread2 10
newcount5 Thread2 10
Thread2 结束
主线程结束
使用lock可以保证同一个线程中,我们期望访问的资源可以保持一致