多线程(python)

gil锁
money = 0

def add():
    global  money
    for x  in range(100000):
        money+=1

def desc():
    global money
    for x in range(100000):
        money -=1

import threading
thread1  = threading.Thread(target=add)
thread2 = threading.Thread(target = desc)
thread1.start()
thread2.start()
print(money)

#输出值
36631
39682
等等诸多的随机值

这是因为什么呢,多线程中如果对全局变量同时操作,会引起这种情况,gil锁会根据执行的字节码行数以及时间片释放gil 在涉及到io操作的时候主动释放,

多线程编程 - threading
#对于io操作来说,多线程与多进程性能差别不大
#通过Thread实例化

import time
import threading
def get_detail_html(url):
    print("get detail html started")
    time.sleep(2)
    print("get detail html end")

def get_detail_url(url):
    print("get detail url started")
    time.sleep(2)
    print("get detail url end")


thread1 = threading.Thread(target=get_detail_html ,args =  ("",))
thread2 = threading.Thread(target=get_detail_url ,args =  ("",))
thread1.setDaemon(True)守护线程如果这儿的值为,等到`主线程`结束的时候会被killi掉
thread1.setDaemon(True)#守护线程如果这儿的值为,等到主线程结束的时候会被killi掉
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("end")

上方的thread1.setDaemon(True) 如果主线程早于thread1线程结束的话那么此线程,会被销毁,如果早于主线程结束 那么主线程不会对thread1产生影响。

join方法中意思与上方的相反,意思是之后执行完当前用jion方法的线程之后才会运行下方的代码

上方的创建线程的方法应用于较小的程序,相对于较大的程序还有如下创建线程的一种方法


#通过继承Thread来实现多线程

import threading

class GetDetailHtml(threading.Thread):
    def __init__(self,name):
        super() .__init__(name = name)

    def run(self): #此方法写的就是要实现的逻辑
        print("get detail html started")
        time.sleep(2)
        print("get detail html end")
thread1 = GetDetailHtml("111")
thread1.start()

print("end")

线程间通信 - 共享变量和 Queue

共享变量 (不安全)并不太安全

#线程间通信
#1线程通讯方式 共享变量
detail_url_list =[]
import time
import threading
def get_detail_html(url):
    #爬去文章的详情页
    global detail_url_list
    url = detail_url_list.pop() #从队列尾部弹出数据
    print("get detail html started")
    time.sleep(2)
    print("get detail html end")

def get_detail_url(url):
    global detail_url_list
    #爬取文章列表页
    print("get detail url started")
    time.sleep(4)
    for i in range(20):
        detail_url_list.append(i)
    print("get detail url end")


thread_detail_url  = threading.Thread(target= get_detail_url)
thread_detail_html  =threading.Thread(target= get_detail_html)


print("end")

condition 使用
import threading

#条件变量, 用于复杂的线程间同步
# class XiaoAi(threading.Thread):
#     def __init__(self, lock):
#         super().__init__(name="小爱")
#         self.lock = lock
#
#     def run(self):
#         self.lock.acquire()
#         print("{} : 在 ".format(self.name))
#         self.lock.release()
#
#         self.lock.acquire()
#         print("{} : 好啊 ".format(self.name))
#         self.lock.release()
#
# class TianMao(threading.Thread):
#     def __init__(self, lock):
#         super().__init__(name="天猫精灵")
#         self.lock = lock
#
#     def run(self):
#
#         self.lock.acquire()
#         print("{} : 小爱同学 ".format(self.name))
#         self.lock.release()
#
#         self.lock.acquire()
#         print("{} : 我们来对古诗吧 ".format(self.name))
#         self.lock.release()

#通过condition完成协同读诗

class XiaoAi(threading.Thread):
    def __init__(self, cond):
        super().__init__(name="小爱")
        self.cond = cond

    def run(self):
        with self.cond:
            self.cond.wait()
            print("{} : 在 ".format(self.name))
            self.cond.notify()

            self.cond.wait()
            print("{} : 好啊 ".format(self.name))
            self.cond.notify()

            self.cond.wait()
            print("{} : 君住长江尾 ".format(self.name))
            self.cond.notify()

            self.cond.wait()
            print("{} : 共饮长江水 ".format(self.name))
            self.cond.notify()

            self.cond.wait()
            print("{} : 此恨何时已 ".format(self.name))
            self.cond.notify()

            self.cond.wait()
            print("{} : 定不负相思意 ".format(self.name))
            self.cond.notify()

class TianMao(threading.Thread):
    def __init__(self, cond):
        super().__init__(name="天猫精灵")
        self.cond = cond

    def run(self):
        with self.cond:
            print("{} : 小爱同学 ".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 我们来对古诗吧 ".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 我住长江头 ".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 日日思君不见君 ".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 此水几时休 ".format(self.name))
            self.cond.notify()
            self.cond.wait()

            print("{} : 只愿君心似我心 ".format(self.name))
            self.cond.notify()
            self.cond.wait()



if __name__ == "__main__":
    from concurrent import futures
    cond = threading.Condition()
    xiaoai = XiaoAi(cond)
    tianmao = TianMao(cond)

    #启动顺序很重要
    #在调用with cond之后才能调用wait或者notify方法
    #condition有两层锁, 一把底层锁会在线程调用了wait方法的时候释放, 上面的锁会在每次调用wait的时候分配一把并放入到cond的等待队列中,等到notify方法的唤醒
    xiaoai.start()
    tianmao.start()

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,523评论 1 15
  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 3,018评论 1 18
  •   一个任务通常就是一个程序,每个运行中的程序就是一个进程。当一个程序运行时,内部可能包含了多个顺序执行流,每个顺...
    OmaiMoon阅读 1,738评论 0 12
  • 前言:为什么有人说 Python 的多线程是鸡肋,不是真正意义上的多线程? 看到这里,也许你会疑惑。这很正常,所以...
    猴哥爱读书阅读 51,787评论 6 69
  • 今天下班比较早,去学校接孩子回来,这小孩习惯了礼拜五回来不喜欢写作业,再她看来礼拜五就跟解放了一样,我问她,她就说...
    于泽欣妈妈阅读 186评论 0 1