网络编程---第十一课:线程,共享资源,锁

参考连接:https://blog.csdn.net/qq_37615098/article/details/83933614

## 线程的概念

**进程的概念:运行着的程序

每个进程里面至少有一个线程

线程是操作系统创建的,用力啊控制代码执行的数据结构

线程就像代码的执行许可证**

**单线程程序。主线程的入口就是代码的开头

主线程顺序往下执行,直到所有的代码都执行完**

**

## 概念对应(银行里面办理业务)

**

***一个服务窗口 = CPU的一个核

客户 = 进程(运行着的程序)

调度员 = 操作系统(OS)

服务号 = 线程

调度员分配服务号给客户 = OS分配线程给进程代码

服务窗口给客户办理业务 = CPU核心执行线程代码***

## 调度的概念

        调度员分配窗口给客户

        一个客户不一定占用一个窗口直到它结束

        比如需要很长时间填写表格

        这是可以让下一个客户办理

        先前的客户填好了表格,在继续


    操作系统不会让一个线程一直占用CPU的

## 进程里的多线程

**线程库**

***代码通过系统调用,请求os分配一个新的线程

python里面使用封装好的库,python3只有threading,是标准库里面的

    thread

    threading

    都可以用来创建和管理线程

    thread比较底层

    threading是thread模块的扩展,提供了很多线程同步功能,使用起来更加方便强大***

例子:

    print("main thread start.")


    import threading

    from time import sleep


    def thread1_entry():

        print("child thread 1,start")

        sleep(15)

        print("child thread 1,end")


    t1 = threading.Thread(target=thread1_entry)    #Thread是一个类Thread()是实例化一个类,传入初始化方法的参数,target传的是这个函数的名字,不是调用。不加括号是函数的对象,target指定了线程对象的入口函数。函数的名字,并没有加括号,意味着target传入的值是一个函数对象,如果加(),target就变成了函数调用的返回值。执行起来的时候,入口函数就是thread1_entry,t1只是对应一个thread模块,要想执行要调用thread的start方法。新的线程执行入口函数里面的代码。

    t1.start()    #t1是Thread的实例对象,从这个点开始就启动了一个新的线程

    sleep(10)    #主线程要sleep10秒    主线程先结束

    print("main thread end.")

**#结果**

    main thread start.

    child thread 1,start

    main thread end.

    child thread 1,end

***有些场景是:主线程要等待子线程执行完,比如子线程爬去数据,主线程分析数据、

要等到子线程结束(线程的.join()方法)***

    import threading

    from time import sleep,ctime,time


    def thread1_entry(nsec):

        print("child thread 1,start at:",ctime())

        sleep(nsec)

        print("child thread 1,end at:",ctime())



    def thread2_entry(nsec):

        print("child thread 2,start at:",ctime())

        sleep(nsec)

        print("child thread 2,end at:",ctime())



    print("main thread start.")

    #创建线程对象,指定了新线程的入口函数,args是传入入口函数的参数

    t1 = threading.Thread(target=thread1_entry,args=(1,))    #Thread是一个类Thread()是实例化一个类,传入初始化方法的参数

    t2 = threading.Thread(target=thread2_entry,args=(2,))  #(1,)元组,args=(1,)是入口函数的参数,就是用args传给他,只能传元组,一个元素的时候,一定要加逗号,这里是传入的是时间


    #启动新线程

    t1.start()  #两个线程的实例化。调用start方法

    t2.start()


    start = time()    #验证json等待的时间


    #主线程等待t1线程结束,

    t1.join()

    #主线程等待t2线程结束

    t2.join()


    end = time()        #验证json等待的时间

    print(end-start)        #验证json等待的时间


    print("main thread end.")

#结果:

    # main thread start.

    # child thread 1,start at: Sat Nov 10 18:06:26 2018

    # child thread 2,start at: Sat Nov 10 18:06:26 2018

    # child thread 1,end at: Sat Nov 10 18:06:27 2018

    # child thread 2,end at: Sat Nov 10 18:06:28 2018

    # 2.0

    # main thread end.

多线程使用局部变量不会乱套, 多线程使用全局变量会乱套

## 多线程使用共享数据

## 共享对象的概念

**从例子说起

高铁上的测试

某个时刻只能一个人使用

进入后往往立刻锁门(表示已经被使用)

看到的人,门口排队等待

用完开锁(表示已经使用完了)

排队的人中下一个去使用(重复这个过程)**

**有些资源是某个时刻时刻独占使用的

如果不加锁

    某人使用厕所

    另一个人也进入使用

    发生冲突

锁保证了

    只有一个人去使用

    别人必须等待**


    import threading

    from time import sleep,ctime,time


    #存储支付宝账号余额

    zhifubao = {

        "jcy":100000,

        "liming":5000,

        "wangmin":15000,

        "zhaolei":6500000,

    }

    #线程1:滴滴打车处理,参数是用户账户和扣款金额

    def thread1_didi_pay(account,amount):

        print("* t1:get balance from bank")

        balance = zhifubao[account]    #通过账户把余额取出来,放到一个变量里面


        #下面的sleep(2)表示一些处理过程中需要花上2秒钟

        print("* t1:do something(like discount lookup) for 2 seconds")

        sleep(2)


        print("* t1:deduct")


        zhifubao[account] = balance - amount    #把余额扣掉


    #线程2:余额宝处理,参数是用户账户和当前利息


    def thread2_yuebao_interest(account, amount):

        print("$ t2:get balance from bank")

        balance = zhifubao[account]


        # 下面的sleep(1)表示一些处理过程中需要花上1秒钟

        print("$ t2:do something2...... for 2 seconds")

        sleep(1)


        print("$ t2: add")


        zhifubao[account] = balance + amount    ##余额每天的收益



    t1 = threading.Thread(target=thread1_didi_pay,args=("jcy",10))  #创立两个线程对象

    t2 = threading.Thread(target=thread2_yuebao_interest,args=("jcy",10))


    t1.start()

    t2.start()


    t1.join()

    t2.join()

    print("finally,jcy balance is %s"%zhifubao["jcy"])

#结果

    # * t1:get balance from bank

    # * t1:do something(like discount lookup) for 2 seconds

    # $ t2:get balance from bank

    # $ t2:do something2...... for 2 seconds

    # $ t2: add

    # * t1:deduct

    # finally,jcy balance is 99990

**#应该是10万元**

#多个线程要访问共享数据的时候,特别是要修改数据的时候。我们可以使用**锁对象的机制**。同时只有一个线程处理他的时候,就不会有问题


    import threading

    from time import sleep,ctime,time


    #存储支付宝账号余额

    zhifubao = {

        "jcy":100000,

        "liming":5000,

        "wangmin":15000,

        "zhaolei":6500000,

    }


    #调用Lock函数,返回一个锁对象

    zhifubao_lock = threading.Lock()


    #线程1:滴滴打车处理,参数是用户账户和扣款金额

    def thread1_didi_pay(account,amount):

        #在代码访问共享对象之前,加锁

        #当多个线程同时执行lock.acquire()时,

        #只有一个线程能成功的获取锁,然后继续执行代码

        #其他线程就继续等待,直到获得锁为止

        zhifubao_lock.acquire()

        print("* t1:get balance from bank")

        balance = zhifubao[account]    #通过账户把余额取出来,放到一个变量里面


        #下面的sleep(2)表示一些处理过程中需要花上2秒钟

        print("* t1:do something(like discount lookup) for 2 seconds")

        sleep(2)


        print("* t1:deduct")


        zhifubao[account] = balance - amount    #把余额扣掉

        #访问共享对象释放锁

        #访问结束后,一定要调用Lock对象的release方法,进行解锁操作

        #否则其他等待锁的线程将永远等待下去

        zhifubao_lock.release()

    #线程2:余额宝处理,参数是用户账户和当前利息


    def thread2_yuebao_interest(account, amount):

        zhifubao_lock.acquire()  #代码访问共享对象之前,加锁

        print("$ t2:get balance from bank")

        balance = zhifubao[account]


        # 下面的sleep(1)表示一些处理过程中需要花上1秒钟

        print("$ t2:do something2...... for 2 seconds")

        sleep(1)


        print("$ t2: add")


        zhifubao[account] = balance + amount    ##余额每天的收益

        zhifubao_lock.release()    #访问完共享对象 释放锁


    t1 = threading.Thread(target=thread1_didi_pay,args=("jcy",10))  #创立两个线程对象

    t2 = threading.Thread(target=thread2_yuebao_interest,args=("jcy",10))


    t1.start()

    t2.start()


    t1.join()

    t2.join()

    print("finally,jcy balance is %s"%zhifubao["jcy"])

#结果

    # * t1:get balance from bank

    # * t1:do something(like discount lookup) for 2 seconds

    # * t1:deduct

    # $ t2:get balance from bank

    # $ t2:do something2...... for 2 seconds

    # $ t2: add

    # finally,jcy balance is 100000   

![在这里插入图片描述](https://img-blog.csdnimg.cn/20181110214842734.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3NjE1MDk4,size_16,color_FFFFFF,t_70)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容