python多线程同步实例教程


Posted in Python onAugust 11, 2019

前言

进程之间通信与线程同步是一个历久弥新的话题,对编程稍有了解应该都知道,但是细说又说不清。一方面除了工作中可能用的比较少,另一方面就是这些概念牵涉到的东西比较多,而且相对较深。网络编程,服务端编程,并发应用等都会涉及到。其开发和调试过程都不直观。由于同步通信机制的原理都是想通的,本文希通过望借助python实例来将抽象概念具体化。

阅读之前可以参考之前的一篇文章:python多线程与多进程及其区别,了解一下线程和进程的创建。

python多线程同步

python中提供两个标准库thread和threading用于对线程的支持,python3中已放弃对前者的支持,后者是一种更高层次封装的线程库,接下来均以后者为例。

同步与互斥

相信多数学过操作系统的人,都被这两个概念弄混过,什么互斥是特殊的同步,同步是多线程或多进程协同完成某一任务过程中在一些关键节点上进行的协同的关系等等。

其实这两个概念都是围绕着一个协同关系来进行的,可以通过一个具体的例子来清晰的表达这两个概念:

有两个线程,分别叫做线程A和线程B,其中线程A用来写一个变量,线程B读取线程A写的变量,而且线程A先写变量,然后线程B才能读这个变量,那么线程A和B之间就是一种同步关系;

===== 同步关系 =====
Thread A:
write(share_data)
V(S) # 释放资源

Thread B:
P(S) # 获取资源
read(share_data)

如果又来一个线程C,也要写这个变量,那么线程A和C之间就是一种互斥关系,因为同时只能由一个线程写该变量;

===== 互斥关系 =====
Thread A:
Lock.acquire();  # 获得锁
write(share_data)
Lock.release()  # 释放锁

Thread C:
Lock.acquire();  # 获得锁
write(share_data)
Lock.release()  # 释放锁

线程同步

主线程和其创建的线程之间各自执行自己的代码直到结束。接下来看一下python线程之间同步问题.

交替执行的线程安全吗?

先来看一下下面的这个例子:

share_data = 0

def tstart(arg):
 time.sleep(0.1)
 global share_data
 for i in xrange(1000):
  share_data += 1

if __name__ == '__main__':
 t1 = threading.Thread(target = tstart, args = ('',))
 t2 = threading.Thread(target = tstart, args = ('',))
 t1.start()
 t2.start()
 t1.join()
 t2.join()
 print 'share_data result:', share_data

上面这段代码执行结果share_data多数情况下会小于2000,上一篇文章介绍过,python解释器CPython中引入了一个全局解释器锁(GIL),也就是任一时刻都只有一个线程在执行,但是这里还会出问题,为什么?

根本原因在于对share_data的写不是原子操作,线程在写的过程中被打断,然后切换线程执行,回来时会继续执行被打断的写操作,不过可能覆盖掉这段时间另一个线程写的结果。

下面是一种可能的运算过程:

python多线程同步实例教程

实际计算过程可能比上面描述的更复杂,可以从单个线程的角度来理解,如果不加同步措施,对于单个线程而言其完全感知不到其他线程的存在,读取数据、计算、写回数据。

如果在读取数据之后,计算过程或者写回数据前被打断,当再次执行时,即使内存中的share_data已经发生了变化,但是该进程还是会从中断的地方继续执行,并将计算结果覆盖掉当前的share_data的值;

这就是为什么每一时刻只有一个线程在执行,但是结果还是错的原因。可以想象如果多个线程并行执行,不加同步措施,那么计算过程会更加混乱。

感兴趣的话可以使用一个全局列表的res,记录下每个线程写share_data的过程,可以比较直观的看到写的过程:

share_data = 0
res = []

def tstart(arg):
 time.sleep(0.1)
 global share_data
 for i in xrange(1000):
  res.append((arg, share_data))
  share_data += 1

if __name__ == '__main__':
 t1 = threading.Thread(target = tstart, args = ('1',))
 t2 = threading.Thread(target = tstart, args = ('2',))
 t1.start()
 t2.start()
 t1.join()
 t2.join()
 print res, len(res)
 print 'share_data result:', share_data

下面是一种可能的结果,可以看到两个线程对share_data的确进行了2000次加一操作,但是结果却不是2000.

[('2', 0), ('2', 1), ('1', 2), ('1', 3), ('1', 4), ('1', 5), ('1', 6), ('1', 7), ('1', 8), ('1', 9), ('1', 10), ('1', 11), ('1', 12), ('2', 12), ('2', 13), ('2', 14), ('2', 15), ('2', 16), ('2', 17), ('2', 18), ('2', 19), ('2', 20), ('2', 21), ('2', 22), ('1', 13), ('1', 14), ('1', 15), ('1', 16), ('1', 17), ('1', 18), ('1', 19), ('1', 20), ('1', 21), ('1', 22), ('1', 23), ('2', 24), ('2', 25), ('2', 26), ('2', 27), ('2', 28), ('2', 29), ('2', 30), ('2', 31), ('2', 32), ('2', 33), ('2', 34), ('1', 35), ('1', 36), ('1', 37), ('1', 38), ('1', 39), ('1', 40), ('1', 41), ('1', 42), ('1', 43), ('1', 44), ('1', 45), ('2', 35), ('2', 47), ('2', 48), ('2', 49), ('2', 50), ('2', 51), ('2', 52), ('2', 53), ('2', 54), ('2', 55), ('2', 56), ('2', 57), ('1', 57), ('1', 58), ('1', 59), ('1', 60), ('1', 61), ('1', 62), ('1', 63), ('1', 64), ('1', 65), ('1', 66), ('1', 67), ('2', 58), ('2', 59), ('2', 60), ('2', 61), ('2', 62), ('2', 63), ('2', 64), ('2', 65), ('2', 66), ('2', 67), ('2', 68), ('1', 68), ('1', 70), ('1', 71), ('1', 72), ('1', 73), ('1', 74), ('1', 75), ('1', 76), ('1', 77), ('1', 78), ('1', 79), ('1', 80), ('2', 80), ('2', 81), ('2', 82), ('2', 83), ('2', 84), ('2', 85), ('2', 86), ('2', 87), ('2', 88), ('2', 89), ('2', 90), ('1', 81), ('1', 82), ('1', 83), ('1', 84), ('1', 85), ('1', 86), ('1', 87), ('1', 88), ('1', 89), ('1', 90), ('1', 91), ('2', 92), ('2', 93), ('2', 94), ('2', 95), ('2', 96), ('2', 97), ('2', 98), ('2', 99), ('2', 100), ('2', 101), ('2', 102), ('1', 103), ('1', 104), ('1', 105), ('1', 106), ('1', 107), ('1', 108), ('1', 109), ('1', 110), ('1', 111), ('1', 112), ('1', 113), ('2', 103), ('2', 115), ('2', 116), ('2', 117), ('2', 118), ('2', 119), ('2', 120), ('2', 121), ('2', 122), ('2', 123), ('2', 124), ('2', 125), ('1', 125), ('1', 126), ('1', 127), ('1', 128), ('1', 129), ('1', 130), ('1', 131), ('1', 132), ('1', 133), ('1', 134), ('1', 135), ('2', 137), ('2', 138), ('2', 139), ('2', 140), ('2', 141), ('2', 142), ('2', 143), ('2', 144), ('2', 145), ('2', 146), ('2', 147), ('1', 136), ('1', 148), ('1', 149), ('1', 150), ('1', 151), ('1', 152), ('1', 153), ('1', 154), ('1', 155), ('1', 156), ('1', 157), ('1', 158), ('2', 148), ('2', 149), ('2', 150), ('2', 151), ('2', 152), ('2', 153), ('2', 154), ('2', 155), ('2', 156), ('2', 157), ('2', 158), ('1', 160), ('1', 161), ('1', 162), ('1', 163), ('1', 164), ('1', 165), ('1', 166), ('1', 167), ('1', 168), ('1', 169), ('1', 170), ('2', 170), ('2', 171), ('2', 172), ('2', 173), ('2', 174), ('2', 175), ('2', 176), ('2', 177), ('2', 178), ('2', 179), ('2', 180), ('1', 171), ('1', 172), ('1', 173), ('1', 174), ('1', 175), ('1', 176), ('1', 177), ('1', 178), ('1', 179), ('1', 180), ('1', 181), ('2', 182), ('2', 183), ('2', 184), ('2', 185), ('2', 186), ('2', 187), ('2', 188), ('2', 189), ('2', 190), ('2', 191), ('2', 192), ('1', 193), ('1', 194), ('1', 195), ('1', 196), ('1', 197), ('1', 198), ('1', 199), ('1', 200), ('1', 201), ('1', 202), ('1', 203), ('2', 193), ('2', 205), ('2', 206), ('2', 207), ('2', 208), ('2', 209), ('2', 210), ('2', 211), ('2', 212), ('2', 213), ('2', 214), ('2', 215), ('1', 215), ('1', 216), ('1', 217), ('1', 218), ('1', 219), ('1', 220), ('1', 221), ('1', 222), ('1', 223), ('1', 224), ('1', 225), ('2', 216), ('2', 217), ('2', 218), ('2', 219), ('2', 220), ('2', 221), ('2', 222), ('2', 223), ('2', 224), ('2', 225), ('2', 226), ('1', 226), ('1', 228), ('1', 229), ('1', 230), ('1', 231), ('1', 232), ('1', 233), ('1', 234), ('1', 235), ('1', 236), ('1', 237), ('1', 238), ('2', 238), ('2', 239), ('2', 240), ('2', 241), ('2', 242), ('2', 243), ('2', 244), ('2', 245), ('2', 246), ('2', 247), ('2', 248), ('1', 239), ('1', 240), ('1', 241), ('1', 242), ('1', 243), ('1', 244), ('1', 245), ('1', 246), ('1', 247), ('1', 248), ('1', 249), ('2', 250), ('2', 251), ('2', 252), ('2', 253), ('2', 254), ('2', 255), ('2', 256), ('2', 257), ('2', 258), ('2', 259), ('2', 260), ('1', 261), ('1', 262), ('1', 263), ('1', 264), ('1', 265), ('1', 266), ('1', 267), ('1', 268), ('1', 269), ('1', 270), ('1', 271), ('2', 261), ('2', 273), ('2', 274), ('2', 275), ('2', 276), ('2', 277), ('2', 278), ('2', 279), ('2', 280), ('2', 281), ('2', 282), ('2', 283), ('1', 283), ('1', 284), ('1', 285), ('1', 286), ('1', 287), ('1', 288), ('1', 289), ('1', 290), ('1', 291), ('1', 292), ('1', 293), ('2', 295), ('2', 296), ('2', 297), ('2', 298), ('2', 299), ('2', 300), ('2', 301), ('2', 302), ('2', 303), ('2', 304), ('2', 305), ('1', 294), ('1', 306), ('1', 307), ('1', 308), ('1', 309), ('1', 310), ('1', 311), ('1', 312), ('1', 313), ('1', 314), ('1', 315), ('1', 316), ('2', 306), ('2', 307), ('2', 308), ('2', 309), ('2', 310), ('2', 311), ('2', 312), ('2', 313), ('2', 314), ('2', 315), ('2', 316), ('1', 318), ('1', 319), ('1', 320), ('1', 321), ('1', 322), ('1', 323), ('1', 324), ('1', 325), ('1', 326), ('1', 327), ('1', 328), ('2', 328), ('2', 329), ('2', 330), ('2', 331), ('2', 332), ('2', 333), ('2', 334), ('2', 335), ('2', 336), ('2', 337), ('2', 338), ('1', 329), ('1', 330), ('1', 331), ('1', 332), ('1', 333), ('1', 334), ('1', 335), ('1', 336), ('1', 337), ('1', 338), ('1', 339), ('2', 340), ('2', 341), ('2', 342), ('2', 343), ('2', 344), ('2', 345), ('2', 346), ('2', 347), ('2', 348), ('2', 349), ('2', 350), ('1', 351), ('1', 352), ('1', 353), ('1', 354), ('1', 355), ('1', 356), ('1', 357), ('1', 358), ('1', 359), ('1', 360), ('1', 361), ('2', 351), ('2', 363), ('2', 364), ('2', 365), ('2', 366), ('2', 367), ('2', 368), ('2', 369), ('2', 370), ('2', 371), ('2', 372), ('2', 373), ('1', 373), ('1', 374), ('1', 375), ('1', 376), ('1', 377), ('1', 378), ('1', 379), ('1', 380), ('1', 381), ('1', 382), ('1', 383), ('2', 374), ('2', 375), ('2', 376), ('2', 377), ('2', 378), ('2', 379), ('2', 380), ('2', 381), ('2', 382), ('2', 383), ('2', 384), ('1', 384), ('1', 386), ('1', 387), ('1', 388), ('1', 389), ('1', 390), ('1', 391), ('1', 392), ('1', 393), ('1', 394), ('1', 395), ('1', 396), ('2', 396), ('2', 397), ('2', 398), ('2', 399), ('2', 400), ('2', 401), ('2', 402), ('2', 403), ('2', 404), ('2', 405), ('2', 406), ('1', 397), ('1', 398), ('1', 399), ('1', 400), ('1', 401), ('1', 402), ('1', 403), ('1', 404), ('1', 405), ('1', 406), ('1', 407), ('2', 408), ('2', 409), ('2', 410), ('2', 411), ('2', 412), ('2', 413), ('2', 414), ('2', 415), ('2', 416), ('2', 417), ('2', 418), ('1', 419), ('1', 420), ('1', 421), ('1', 422), ('1', 423), ('1', 424), ('1', 425), ('1', 426), ('1', 427), ('1', 428), ('1', 429), ('2', 419), ('2', 431), ('2', 432), ('2', 433), ('2', 434), ('2', 435), ('2', 436), ('2', 437), ('2', 438), ('2', 439), ('2', 440), ('2', 441), ('1', 441), ('1', 442), ('1', 443), ('1', 444), ('1', 445), ('1', 446), ('1', 447), ('1', 448), ('1', 449), ('1', 450), ('1', 451), ('2', 453), ('2', 454), ('2', 455), ('2', 456), ('2', 457), ('2', 458), ('2', 459), ('2', 460), ('2', 461), ('2', 462), ('2', 463), ('1', 452), ('1', 464), ('1', 465), ('1', 466), ('1', 467), ('1', 468), ('1', 469), ('1', 470), ('1', 471), ('1', 472), ('1', 473), ('1', 474), ('2', 464), ('2', 465), ('2', 466), ('2', 467), ('2', 468), ('2', 469), ('2', 470), ('2', 471), ('2', 472), ('2', 473), ('2', 474), ('1', 476), ('1', 477), ('1', 478), ('1', 479), ('1', 480), ('1', 481), ('1', 482), ('1', 483), ('1', 484), ('1', 485), ('1', 486), ('2', 486), ('2', 487), ('2', 488), ('2', 489), ('2', 490), ('2', 491), ('2', 492), ('2', 493), ('2', 494), ('2', 495), ('2', 496), ('1', 487), ('1', 488), ('1', 489), ('1', 490), ('1', 491), ('1', 492), ('1', 493), ('1', 494), ('1', 495), ('1', 496), ('1', 497), ('2', 498), ('2', 499), ('2', 500), ('2', 501), ('2', 502), ('2', 503), ('2', 504), ('2', 505), ('2', 506), ('2', 507), ('2', 508), ('1', 509), ('1', 510), ('1', 511), ('1', 512), ('1', 513), ('1', 514), ('1', 515), ('1', 516), ('1', 517), ('1', 518), ('1', 519), ('2', 509), ('2', 521), ('2', 522), ('2', 523), ('2', 524), ('2', 525), ('2', 526), ('2', 527), ('2', 528), ('2', 529), ('2', 530), ('2', 531), ('1', 531), ('1', 532), ('1', 533), ('1', 534), ('1', 535), ('1', 536), ('1', 537), ('1', 538), ('1', 539), ('1', 540), ('1', 541), ('2', 532), ('2', 533), ('2', 534), ('2', 535), ('2', 536), ('2', 537), ('2', 538), ('2', 539), ('2', 540), ('2', 541), ('2', 542), ('1', 542), ('1', 544), ('1', 545), ('1', 546), ('1', 547), ('1', 548), ('1', 549), ('1', 550), ('1', 551), ('1', 552), ('1', 553), ('1', 554), ('2', 554), ('2', 555), ('2', 556), ('2', 557), ('2', 558), ('2', 559), ('2', 560), ('2', 561), ('2', 562), ('2', 563), ('2', 564), ('1', 555), ('1', 556), ('1', 557), ('1', 558), ('1', 559), ('1', 560), ('1', 561), ('1', 562), ('1', 563), ('1', 564), ('1', 565), ('2', 566), ('2', 567), ('2', 568), ('2', 569), ('2', 570), ('2', 571), ('2', 572), ('2', 573), ('2', 574), ('2', 575), ('2', 576), ('1', 577), ('1', 578), ('1', 579), ('1', 580), ('1', 581), ('1', 582), ('1', 583), ('1', 584), ('1', 585), ('1', 586), ('1', 587), ('2', 577), ('2', 589), ('2', 590), ('2', 591), ('2', 592), ('2', 593), ('2', 594), ('2', 595), ('2', 596), ('2', 597), ('2', 598), ('2', 599), ('1', 599), ('1', 600), ('1', 601), ('1', 602), ('1', 603), ('1', 604), ('1', 605), ('1', 606), ('1', 607), ('1', 608), ('1', 609), ('2', 611), ('2', 612), ('2', 613), ('2', 614), ('2', 615), ('2', 616), ('2', 617), ('2', 618), ('2', 619), ('2', 620), ('2', 621), ('1', 610), ('1', 622), ('1', 623), ('1', 624), ('1', 625), ('1', 626), ('1', 627), ('1', 628), ('1', 629), ('1', 630), ('1', 631), ('1', 632), ('2', 622), ('2', 623), ('2', 624), ('2', 625), ('2', 626), ('2', 627), ('2', 628), ('2', 629), ('2', 630), ('2', 631), ('2', 632), ('1', 634), ('1', 635), ('1', 636), ('1', 637), ('1', 638), ('1', 639), ('1', 640), ('1', 641), ('1', 642), ('1', 643), ('1', 644), ('2', 644), ('2', 645), ('2', 646), ('2', 647), ('2', 648), ('2', 649), ('2', 650), ('2', 651), ('2', 652), ('2', 653), ('2', 654), ('1', 645), ('1', 646), ('1', 647), ('1', 648), ('1', 649), ('1', 650), ('1', 651), ('1', 652), ('1', 653), ('1', 654), ('1', 655), ('2', 656), ('2', 657), ('2', 658), ('2', 659), ('2', 660), ('2', 661), ('2', 662), ('2', 663), ('2', 664), ('2', 665), ('2', 666), ('1', 667), ('1', 668), ('1', 669), ('1', 670), ('1', 671), ('1', 672), ('1', 673), ('1', 674), ('1', 675), ('1', 676), ('1', 677), ('2', 667), ('2', 679), ('2', 680), ('2', 681), ('2', 682), ('2', 683), ('2', 684), ('2', 685), ('2', 686), ('2', 687), ('2', 688), ('2', 689), ('1', 689), ('1', 690), ('1', 691), ('1', 692), ('1', 693), ('1', 694), ('1', 695), ('1', 696), ('1', 697), ('1', 698), ('1', 699), ('2', 690), ('2', 691), ('2', 692), ('2', 693), ('2', 694), ('2', 695), ('2', 696), ('2', 697), ('2', 698), ('2', 699), ('2', 700), ('1', 700), ('1', 702), ('1', 703), ('1', 704), ('1', 705), ('1', 706), ('1', 707), ('1', 708), ('1', 709), ('1', 710), ('1', 711), ('1', 712), ('2', 712), ('2', 713), ('2', 714), ('2', 715), ('2', 716), ('2', 717), ('2', 718), ('2', 719), ('2', 720), ('2', 721), ('2', 722), ('1', 713), ('1', 714), ('1', 715), ('1', 716), ('1', 717), ('1', 718), ('1', 719), ('1', 720), ('1', 721), ('1', 722), ('1', 723), ('2', 724), ('2', 725), ('2', 726), ('2', 727), ('2', 728), ('2', 729), ('2', 730), ('2', 731), ('2', 732), ('2', 733), ('2', 734), ('1', 735), ('1', 736), ('1', 737), ('1', 738), ('1', 739), ('1', 740), ('1', 741), ('1', 742), ('1', 743), ('1', 744), ('1', 745), ('2', 735), ('2', 747), ('2', 748), ('2', 749), ('2', 750), ('2', 751), ('2', 752), ('2', 753), ('2', 754), ('2', 755), ('2', 756), ('2', 757), ('1', 757), ('1', 758), ('1', 759), ('1', 760), ('1', 761), ('1', 762), ('1', 763), ('1', 764), ('1', 765), ('1', 766), ('1', 767), ('2', 769), ('2', 770), ('2', 771), ('2', 772), ('2', 773), ('2', 774), ('2', 775), ('2', 776), ('2', 777), ('2', 778), ('2', 779), ('1', 768), ('1', 780), ('1', 781), ('1', 782), ('1', 783), ('1', 784), ('1', 785), ('1', 786), ('1', 787), ('1', 788), ('1', 789), ('1', 790), ('2', 780), ('2', 781), ('2', 782), ('2', 783), ('2', 784), ('2', 785), ('2', 786), ('2', 787), ('2', 788), ('2', 789), ('2', 790), ('1', 792), ('1', 793), ('1', 794), ('1', 795), ('1', 796), ('1', 797), ('1', 798), ('1', 799), ('1', 800), ('1', 801), ('1', 802), ('2', 802), ('2', 803), ('2', 804), ('2', 805), ('2', 806), ('2', 807), ('2', 808), ('2', 809), ('2', 810), ('2', 811), ('2', 812), ('1', 803), ('1', 804), ('1', 805), ('1', 806), ('1', 807), ('1', 808), ('1', 809), ('1', 810), ('1', 811), ('1', 812), ('1', 813), ('2', 814), ('2', 815), ('2', 816), ('2', 817), ('2', 818), ('2', 819), ('2', 820), ('2', 821), ('2', 822), ('2', 823), ('2', 824), ('1', 825), ('1', 826), ('1', 827), ('1', 828), ('1', 829), ('1', 830), ('1', 831), ('1', 832), ('1', 833), ('1', 834), ('1', 835), ('2', 825), ('2', 837), ('2', 838), ('2', 839), ('2', 840), ('2', 841), ('2', 842), ('2', 843), ('2', 844), ('2', 845), ('2', 846), ('2', 847), ('1', 847), ('1', 848), ('1', 849), ('1', 850), ('1', 851), ('1', 852), ('1', 853), ('1', 854), ('1', 855), ('1', 856), ('1', 857), ('2', 848), ('2', 849), ('2', 850), ('2', 851), ('2', 852), ('2', 853), ('2', 854), ('2', 855), ('2', 856), ('2', 857), ('2', 858), ('1', 858), ('1', 860), ('1', 861), ('1', 862), ('1', 863), ('1', 864), ('1', 865), ('1', 866), ('1', 867), ('1', 868), ('1', 869), ('1', 870), ('2', 870), ('2', 871), ('2', 872), ('2', 873), ('2', 874), ('2', 875), ('2', 876), ('2', 877), ('2', 878), ('2', 879), ('2', 880), ('1', 871), ('1', 872), ('1', 873), ('1', 874), ('1', 875), ('1', 876), ('1', 877), ('1', 878), ('1', 879), ('1', 880), ('1', 881), ('2', 882), ('2', 883), ('2', 884), ('2', 885), ('2', 886), ('2', 887), ('2', 888), ('2', 889), ('2', 890), ('2', 891), ('2', 892), ('1', 893), ('1', 894), ('1', 895), ('1', 896), ('1', 897), ('1', 898), ('1', 899), ('1', 900), ('1', 901), ('1', 902), ('1', 903), ('2', 893), ('2', 905), ('2', 906), ('2', 907), ('2', 908), ('2', 909), ('2', 910), ('2', 911), ('2', 912), ('2', 913), ('2', 914), ('2', 915), ('1', 915), ('1', 916), ('1', 917), ('1', 918), ('1', 919), ('1', 920), ('1', 921), ('1', 922), ('1', 923), ('1', 924), ('1', 925), ('2', 927), ('2', 928), ('2', 929), ('2', 930), ('2', 931), ('2', 932), ('2', 933), ('2', 934), ('2', 935), ('2', 936), ('2', 937), ('1', 926), ('1', 938), ('1', 939), ('1', 940), ('1', 941), ('1', 942), ('1', 943), ('1', 944), ('1', 945), ('1', 946), ('1', 947), ('1', 948), ('2', 938), ('2', 939), ('2', 940), ('2', 941), ('2', 942), ('2', 943), ('2', 944), ('2', 945), ('2', 946), ('2', 947), ('2', 948), ('1', 950), ('1', 951), ('1', 952), ('1', 953), ('1', 954), ('1', 955), ('1', 956), ('1', 957), ('1', 958), ('1', 959), ('1', 960), ('2', 960), ('2', 961), ('2', 962), ('2', 963), ('2', 964), ('2', 965), ('2', 966), ('2', 967), ('2', 968), ('2', 969), ('2', 970), ('1', 961), ('1', 962), ('1', 963), ('1', 964), ('1', 965), ('1', 966), ('1', 967), ('1', 968), ('1', 969), ('1', 970), ('1', 971), ('2', 972), ('2', 973), ('2', 974), ('2', 975), ('2', 976), ('2', 977), ('2', 978), ('2', 979), ('2', 980), ('2', 981), ('2', 982), ('1', 983), ('1', 984), ('1', 985), ('1', 986), ('1', 987), ('1', 988), ('1', 989), ('1', 990), ('1', 991), ('1', 992), ('1', 993), ('2', 983), ('2', 995), ('2', 996), ('2', 997), ('2', 998), ('2', 999), ('2', 1000), ('2', 1001), ('2', 1002), ('2', 1003), ('2', 1004), ('2', 1005), ('1', 1005), ('1', 1006), ('1', 1007), ('1', 1008), ('1', 1009), ('1', 1010), ('1', 1011), ('1', 1012), ('1', 1013), ('1', 1014), ('1', 1015), ('2', 1006), ('2', 1007), ('2', 1008), ('2', 1009), ('2', 1010), ('2', 1011), ('2', 1012), ('2', 1013), ('2', 1014), ('2', 1015), ('2', 1016), ('1', 1016), ('1', 1018), ('1', 1019), ('1', 1020), ('1', 1021), ('1', 1022), ('1', 1023), ('1', 1024), ('1', 1025), ('1', 1026), ('1', 1027), ('1', 1028), ('2', 1028), ('2', 1029), ('2', 1030), ('2', 1031), ('2', 1032), ('2', 1033), ('2', 1034), ('2', 1035), ('2', 1036), ('2', 1037), ('2', 1038), ('1', 1029), ('1', 1030), ('1', 1031), ('1', 1032), ('1', 1033), ('1', 1034), ('1', 1035), ('1', 1036), ('1', 1037), ('1', 1038), ('1', 1039), ('2', 1040), ('2', 1041), ('2', 1042), ('2', 1043), ('2', 1044), ('2', 1045), ('2', 1046), ('2', 1047), ('2', 1048), ('2', 1049), ('2', 1050), ('1', 1051), ('1', 1052), ('1', 1053), ('1', 1054), ('1', 1055), ('1', 1056), ('1', 1057), ('1', 1058), ('1', 1059), ('1', 1060), ('1', 1061), ('2', 1051), ('2', 1063), ('2', 1064), ('2', 1065), ('2', 1066), ('2', 1067), ('2', 1068), ('2', 1069), ('2', 1070), ('2', 1071), ('2', 1072), ('2', 1073), ('1', 1073), ('1', 1074), ('1', 1075), ('1', 1076), ('1', 1077), ('1', 1078), ('1', 1079), ('1', 1080), ('1', 1081), ('1', 1082), ('1', 1083), ('2', 1085), ('2', 1086), ('2', 1087), ('2', 1088), ('2', 1089), ('2', 1090), ('2', 1091), ('2', 1092), ('2', 1093), ('2', 1094), ('2', 1095), ('1', 1084), ('1', 1096), ('1', 1097), ('1', 1098), ('1', 1099), ('1', 1100), ('1', 1101), ('1', 1102), ('1', 1103), ('1', 1104), ('1', 1105), ('1', 1106), ('2', 1096), ('2', 1097), ('2', 1098), ('2', 1099), ('2', 1100), ('2', 1101), ('2', 1102), ('2', 1103), ('2', 1104), ('2', 1105), ('2', 1106), ('1', 1108), ('1', 1109), ('1', 1110), ('1', 1111), ('1', 1112), ('1', 1113), ('1', 1114), ('1', 1115), ('1', 1116), ('1', 1117), ('1', 1118), ('2', 1118), ('2', 1119), ('2', 1120), ('2', 1121), ('2', 1122), ('2', 1123), ('2', 1124), ('2', 1125), ('2', 1126), ('2', 1127), ('2', 1128), ('1', 1119), ('1', 1120), ('1', 1121), ('1', 1122), ('1', 1123), ('1', 1124), ('1', 1125), ('1', 1126), ('1', 1127), ('1', 1128), ('1', 1129), ('2', 1130), ('2', 1131), ('2', 1132), ('2', 1133), ('2', 1134), ('2', 1135), ('2', 1136), ('2', 1137), ('2', 1138), ('2', 1139), ('2', 1140), ('1', 1141), ('1', 1142), ('1', 1143), ('1', 1144), ('1', 1145), ('1', 1146), ('1', 1147), ('1', 1148), ('1', 1149), ('1', 1150), ('1', 1151), ('2', 1141), ('2', 1153), ('2', 1154), ('2', 1155), ('2', 1156), ('2', 1157), ('2', 1158), ('2', 1159), ('2', 1160), ('2', 1161), ('2', 1162), ('2', 1163), ('1', 1163), ('1', 1164), ('1', 1165), ('1', 1166), ('1', 1167), ('1', 1168), ('1', 1169), ('1', 1170), ('1', 1171), ('1', 1172), ('1', 1173), ('2', 1164), ('2', 1165), ('2', 1166), ('2', 1167), ('2', 1168), ('2', 1169), ('2', 1170), ('2', 1171), ('2', 1172), ('2', 1173), ('2', 1174), ('1', 1174), ('1', 1176), ('1', 1177), ('1', 1178), ('1', 1179), ('1', 1180), ('1', 1181), ('1', 1182), ('1', 1183), ('1', 1184), ('1', 1185), ('1', 1186), ('2', 1186), ('2', 1187), ('2', 1188), ('2', 1189), ('2', 1190), ('2', 1191), ('2', 1192), ('2', 1193), ('2', 1194), ('2', 1195), ('2', 1196), ('1', 1187), ('1', 1188), ('1', 1189), ('1', 1190), ('1', 1191), ('1', 1192), ('1', 1193), ('1', 1194), ('1', 1195), ('1', 1196), ('1', 1197), ('2', 1198), ('2', 1199), ('2', 1200), ('2', 1201), ('2', 1202), ('2', 1203), ('2', 1204), ('2', 1205), ('2', 1206), ('2', 1207), ('2', 1208), ('1', 1209), ('1', 1210), ('1', 1211), ('1', 1212), ('1', 1213), ('1', 1214), ('1', 1215), ('1', 1216), ('1', 1217), ('1', 1218), ('1', 1219), ('2', 1209), ('2', 1221), ('2', 1222), ('2', 1223), ('2', 1224), ('2', 1225), ('2', 1226), ('2', 1227), ('2', 1228), ('2', 1229), ('2', 1230), ('2', 1231), ('1', 1231), ('1', 1232), ('1', 1233), ('1', 1234), ('1', 1235), ('1', 1236), ('1', 1237), ('1', 1238), ('1', 1239), ('1', 1240), ('1', 1241), ('2', 1243), ('2', 1244), ('2', 1245), ('2', 1246), ('2', 1247), ('2', 1248), ('2', 1249), ('2', 1250), ('2', 1251), ('2', 1252), ('2', 1253), ('1', 1242), ('1', 1254), ('1', 1255), ('1', 1256), ('1', 1257), ('1', 1258), ('1', 1259), ('1', 1260), ('1', 1261), ('1', 1262), ('1', 1263), ('1', 1264), ('2', 1254), ('2', 1255), ('2', 1256), ('2', 1257), ('2', 1258), ('2', 1259), ('2', 1260), ('2', 1261), ('2', 1262), ('2', 1263), ('2', 1264), ('1', 1266), ('1', 1267), ('1', 1268), ('1', 1269), ('1', 1270), ('1', 1271), ('1', 1272), ('1', 1273), ('1', 1274), ('1', 1275), ('1', 1276), ('2', 1276), ('2', 1277), ('2', 1278), ('2', 1279), ('2', 1280), ('2', 1281), ('2', 1282), ('2', 1283), ('2', 1284), ('2', 1285), ('2', 1286), ('1', 1277), ('1', 1278), ('1', 1279), ('1', 1280), ('1', 1281), ('1', 1282), ('1', 1283), ('1', 1284), ('1', 1285), ('1', 1286), ('1', 1287), ('2', 1288), ('2', 1289), ('2', 1290), ('2', 1291), ('2', 1292), ('2', 1293), ('2', 1294), ('2', 1295), ('2', 1296), ('2', 1297), ('2', 1298), ('1', 1299), ('1', 1300), ('1', 1301), ('1', 1302), ('1', 1303), ('1', 1304), ('1', 1305), ('1', 1306), ('1', 1307), ('1', 1308), ('1', 1309), ('2', 1299), ('2', 1311), ('2', 1312), ('2', 1313), ('2', 1314), ('2', 1315), ('2', 1316), ('2', 1317), ('2', 1318), ('2', 1319), ('2', 1320), ('2', 1321), ('1', 1321), ('1', 1322), ('1', 1323), ('1', 1324), ('1', 1325), ('1', 1326), ('1', 1327), ('1', 1328), ('1', 1329), ('1', 1330), ('1', 1331), ('2', 1322), ('2', 1323), ('2', 1324), ('2', 1325), ('2', 1326), ('2', 1327), ('2', 1328), ('2', 1329), ('2', 1330), ('2', 1331), ('2', 1332), ('1', 1332), ('1', 1334), ('1', 1335), ('1', 1336), ('1', 1337), ('1', 1338), ('1', 1339), ('1', 1340), ('1', 1341), ('1', 1342), ('1', 1343), ('1', 1344), ('2', 1344), ('2', 1345), ('2', 1346), ('2', 1347), ('2', 1348), ('2', 1349), ('2', 1350), ('2', 1351), ('2', 1352), ('2', 1353), ('2', 1354), ('1', 1345), ('1', 1346), ('1', 1347), ('1', 1348), ('1', 1349), ('1', 1350), ('1', 1351), ('1', 1352), ('1', 1353), ('1', 1354), ('1', 1355), ('2', 1356), ('2', 1357), ('2', 1358), ('2', 1359), ('2', 1360), ('2', 1361), ('2', 1362), ('2', 1363), ('2', 1364), ('2', 1365), ('2', 1366), ('1', 1367), ('1', 1368), ('1', 1369), ('1', 1370), ('1', 1371), ('1', 1372), ('1', 1373), ('1', 1374), ('1', 1375), ('1', 1376), ('1', 1377), ('2', 1367), ('2', 1379), ('2', 1380), ('2', 1381), ('2', 1382), ('2', 1383), ('2', 1384), ('2', 1385), ('2', 1386), ('2', 1387), ('2', 1388), ('2', 1389), ('1', 1389), ('1', 1390), ('1', 1391), ('1', 1392), ('1', 1393), ('1', 1394), ('1', 1395), ('1', 1396), ('1', 1397), ('1', 1398), ('1', 1399), ('2', 1401), ('2', 1402), ('2', 1403), ('2', 1404), ('2', 1405), ('2', 1406), ('2', 1407), ('2', 1408), ('2', 1409), ('2', 1410), ('2', 1411), ('1', 1400), ('1', 1412), ('1', 1413), ('1', 1414), ('1', 1415), ('1', 1416), ('1', 1417), ('1', 1418), ('1', 1419), ('1', 1420), ('1', 1421), ('1', 1422), ('2', 1412), ('2', 1413), ('2', 1414), ('2', 1415), ('2', 1416), ('2', 1417), ('2', 1418), ('2', 1419), ('2', 1420), ('2', 1421), ('2', 1422), ('1', 1424), ('1', 1425), ('1', 1426), ('1', 1427), ('1', 1428), ('1', 1429), ('1', 1430), ('1', 1431), ('1', 1432), ('1', 1433), ('1', 1434), ('2', 1434), ('2', 1435), ('2', 1436), ('2', 1437), ('2', 1438), ('2', 1439), ('2', 1440), ('2', 1441), ('2', 1442), ('2', 1443), ('2', 1444), ('1', 1435), ('1', 1436), ('1', 1437), ('1', 1438), ('1', 1439), ('1', 1440), ('1', 1441), ('1', 1442), ('1', 1443), ('1', 1444), ('1', 1445), ('2', 1446), ('2', 1447), ('2', 1448), ('2', 1449), ('2', 1450), ('2', 1451), ('2', 1452), ('2', 1453), ('2', 1454), ('2', 1455), ('2', 1456), ('1', 1457), ('1', 1458), ('1', 1459), ('1', 1460), ('1', 1461), ('1', 1462), ('1', 1463), ('1', 1464), ('1', 1465), ('1', 1466), ('1', 1467), ('2', 1457), ('2', 1469), ('2', 1470), ('2', 1471), ('2', 1472), ('2', 1473), ('2', 1474), ('2', 1475), ('2', 1476), ('2', 1477), ('2', 1478), ('2', 1479), ('1', 1479), ('1', 1480), ('1', 1481), ('1', 1482), ('1', 1483), ('1', 1484), ('1', 1485), ('1', 1486), ('1', 1487), ('1', 1488), ('1', 1489), ('2', 1480), ('2', 1481), ('2', 1482), ('2', 1483), ('2', 1484), ('2', 1485), ('2', 1486), ('2', 1487), ('2', 1488), ('2', 1489), ('2', 1490), ('1', 1490), ('1', 1492), ('1', 1493), ('1', 1494), ('1', 1495), ('1', 1496), ('1', 1497), ('1', 1498), ('1', 1499), ('1', 1500), ('1', 1501), ('1', 1502), ('2', 1502), ('2', 1503), ('2', 1504), ('2', 1505), ('2', 1506), ('2', 1507), ('2', 1508), ('2', 1509), ('2', 1510), ('2', 1511), ('2', 1512), ('1', 1503), ('1', 1504), ('1', 1505), ('1', 1506), ('1', 1507), ('1', 1508), ('1', 1509), ('1', 1510), ('1', 1511), ('1', 1512), ('1', 1513), ('2', 1514), ('2', 1515), ('2', 1516), ('2', 1517), ('2', 1518), ('2', 1519), ('2', 1520), ('2', 1521), ('2', 1522), ('2', 1523), ('2', 1524), ('1', 1525), ('1', 1526), ('1', 1527), ('1', 1528), ('1', 1529), ('1', 1530), ('1', 1531), ('1', 1532), ('1', 1533), ('1', 1534), ('1', 1535), ('2', 1525), ('2', 1537), ('2', 1538), ('2', 1539), ('2', 1540), ('2', 1541), ('2', 1542), ('2', 1543), ('2', 1544), ('2', 1545), ('2', 1546), ('2', 1547), ('1', 1547), ('1', 1548), ('1', 1549), ('1', 1550), ('1', 1551), ('1', 1552), ('1', 1553), ('1', 1554), ('1', 1555), ('1', 1556), ('1', 1557), ('2', 1559), ('2', 1560), ('2', 1561), ('2', 1562), ('2', 1563), ('2', 1564), ('2', 1565), ('2', 1566), ('2', 1567), ('2', 1568), ('1', 1558), ('1', 1570)] 2000
share_data result: 1571

这就是多线程写操作带来的线程安全问题。具体来说这种线程同步属于互斥关系。接下来看一下python提供的多线程同步措施。

threading模块的给python线程提供了一些同步机制,具体用法可以参照官网上的文档说明。

  • Lock:互斥锁,只能有一个线程获取,获取该锁的线程才能执行,否则阻塞;
  • RLock:递归锁,也称可重入锁,已经获得该锁的线程可以继续多次获得该锁,而不会被阻塞,释放的次数必须和获取的次数相同才会真正释放该锁;
  • Condition:条件变量,使得一个线程等待另一个线程满足特定条件,比如改变状态或某个值。然后会主动通知另一个线程,并主动放弃锁;
  • Semaphore:信号锁。为线程间共享的有限资源提供一个”计数器”,如果没有可用资源则会被阻塞;
  • Event:事件锁,任意数量的线程等待某个事件的发生,在该事件发生后所有线程被激活;
  • Timer:一种计时器(其用法比较简单,不算同步机制暂不介绍)

互斥锁Lock

其基本用法非常简单:

  1. 创建锁:Lock()
  2. 获得锁:acquire([blocking])
  3. 释放锁:release()
import threading
import time
lock = threading.Lock()  # step 1: 创建互斥锁
share_data = 0

def tstart(arg):
 time.sleep(0.1)
 global share_data
 if lock.acquire():  # step 2: 获取互斥锁,否则阻塞当前线程
  share_data += 1
 lock.release()   # step 3: 释放互斥锁

if __name__ == '__main__':
 tlst = list()
 for i in xrange(10):
  t = threading.Thread(target=tstart, args=('',))
  tlst.append(t)
 for t in tlst:
  t.start()
 tlst[2].join()
 print("This is main function at:%s" % time.time())
 print 'share_data result:', share_data

结果:

This is main function at:1564909315.86
share_data result: 7

上面的share_data结果有一定的随机性,因为我们只等待第二个线程执行结束就直接读取结果然后结束主线程了。

不过从上面这个结果我们可以推断出,当第三个线程结束且主线程执行到输出share_data的结果时,至少七个线程完成了对share_data的加1操作;

重入锁RLock

由于当前线程获得锁之后,在释放锁之前有可能再次获取锁导致死锁。python引入了重入锁。

import threading
import time
rlock = threading.RLock()  # step 1: 创建重入锁
share_data = 0

def check_data():
 global share_data
 if rlock.acquire():
  if share_data > 10:
   share_data = 0
 rlock.release()

def tstart(arg):
 time.sleep(0.1)
 global share_data
 if rlock.acquire():  # step 2: 获取重入锁,否则阻塞当前线程
  check_data()
  share_data += 1
 rlock.release()   # step 3: 释放重入锁

if __name__ == '__main__':
 t1 = threading.Thread(target = tstart, args = ('',))
 t1.start()
 t1.join()
 print("This is main function at:%s" % time.time())
 print 'share_data result:', share_data

这个例子如果使用互斥锁,就会导致当前线程阻塞。

信号量Semaphore

信号量有一个初始值,表示当前可用的资源数,多线程执行过程中会动态的加减信号量,信号量某一时刻的值表示的是当前还可以增加的执行的线程的数量;

信号量有两种操作:

  1. acquire(即P操作)
  2. release(即V操作)

执行V操作的线程不受限制,执行P操作的线程当资源不足时会被阻塞;

def get_wait_time():
 return random.random()/5.0

# 资源数0
S = threading.Semaphore(0)
def consumer(name):
 S.acquire()
 time.sleep(get_wait_time())
 print name

def producer(name):
 # time.sleep(0.1)
 time.sleep(get_wait_time())
 print name
 S.release()

if __name__ == "__main__":
 for i in xrange(5, 10):
  c = threading.Thread(target=consumer, args=("consumer:%s"%i, ))
  c.start()
 for i in xrange(5):
  p = threading.Thread(target=producer, args=("producer:%s"%i, ))
  p.start()
 time.sleep(2)

下面是一种可能的执行结果:

producer:3
producer:0
consumer:6
producer:4
producer:1
consumer:5
producer:2
consumer:7
consumer:8
consumer:9

 条件Condition

接下来看一下另一种同步机制条件Condition,该同步条件不是很直观,为了更好的查看其工作过程,先定义一些函数:

def get_time():
 return time.strftime("%Y-%m-%d %H:%M:%S")

def show_start_info(tname):
 print '%s start at: %s' %(tname, get_time())

def show_acquire_info(tname):
 print '%s acquire at: %s' % (tname, time.time())

def show_add_once_res(tname):
 print '%s add: %s at: %s' % (tname, share_data, time.time())

def show_end_info(tname):
 print 'End %s with: %s at: %s' % (tname, share_data, time.time())

def show_wait_info(tname):
 print '%s wait at: %s' % (tname, time.time())

条件变量可以使线程已经获得锁的情况下,在条件不满足的时候可以主动的放弃锁,通知唤醒其他阻塞的线程;基本工作过程如下:

  1. 创建一个全局条件变量对象;
  2. 每一个线程执行前先acquire条件变量,获取则执行,否则阻塞。
  3. 当前执行线程推进过程中会判断一些条件,如果条件不满足则wait并主动释放锁,调用wait会使当前线程阻塞;
  4. 判断条件满足,进行一些处理改变条件后,当前线程通过notify方法通知并唤醒其他线程,其他处于wait状态的线程接到通知后会重新判断条件,若满足其执行条件就执行。注意调用notify不会释放锁;
  5. 不断的重复这一过程,直到任务完成。

这里有一点不好理解,当前线程修改了条件之后,通过notify通知其他线程检查其各自的执行条件是否满足,但是条件变量持有的唯一的锁被当前线程拥有而且没有释放,那么其他线程怎么执行?

Python文档给出的说明如下:

Note: an awakened thread does not actually return from its wait() call until it can reacquire the lock. Since notify() does not release the lock, its caller should.

也就是说notify通知唤醒的线程不会从其wait函数返回,并继续执行,而是直到其获得了条件变量中的锁。调用notify的线程应该主动释放锁,因为notify函数不会释放。

那这里就会有一个问题,当前线程修改了其他线程执行的条件,通知其他线程后并主动调用wait释放锁挂起自己,如果其他线程执行的条件均不满足,那所有线程均会阻塞;

下面通过两个线程交替打印字符"A"和“B”来说明条件变量的使用:

share_data, max_len = '#', 6
cond = threading.Condition()

def addA(tname):
  show_start_info(tname)
  cond.acquire()
  time.sleep(1)
  show_acquire_info(tname)
  global share_data
  while len(share_data) <= max_len:
    if share_data[-1] != 'A':
      share_data += 'A'
      time.sleep(1)
      cond.notify()
      show_add_once_res(tname)
    else:
      # show_wait_info(tname)
      cond.wait()
  cond.release()
  show_end_info(tname)

def addB(tname):
  show_start_info(tname)
  cond.acquire()
  time.sleep(1)
  show_acquire_info(tname)
  global share_data
  while len(share_data) <= max_len:
    if share_data[-1] != 'B':
      share_data += 'B'
      time.sleep(1)
      cond.notify()
      show_add_once_res(tname)
    else:
      # show_wait_info(tname)
      cond.wait()
  cond.release()
  show_end_info(tname)

if __name__ == "__main__":
  t1 = threading.Thread(target=addA, args=("Thread 1", ))
  t2 = threading.Thread(target=addB, args=("Thread 2", ))
  t1.start()
  t2.start()
  t1.join()
  t2.join()
  print "share_data:", share_data

结果:

Thread 1 start at: 2019-08-10 17:47:54
Thread 2 start at: 2019-08-10 17:47:54
Thread 1 acquire at: 1565430475.68
Thread 1 add: #A at: 1565430476.68
Thread 2 acquire at: 1565430477.68
Thread 2 add: #AB at: 1565430478.68
Thread 1 add: #ABA at: 1565430479.68
Thread 2 add: #ABAB at: 1565430480.68
Thread 1 add: #ABABA at: 1565430481.68
Thread 2 add: #ABABAB at: 1565430482.68
End Thread 2 with: #ABABAB at: 1565430482.68
End Thread 1 with: #ABABAB at: 1565430482.68
share_data: #ABABAB

结果中可以看出双线程执行的过程以及时间节点。

事件Event

最后再来看一种简单粗暴的线程间同步方式:Event.

该方式的核心就是使用事件控制一个全局变量的状态:True or False。线程执行过程中先判断变量的值,为True就执行,否则调用wait阻塞自己;

当全局变量的状态被set为True时,会唤醒所有调用wait而进入阻塞状态的线程;需要暂停所有线程时,使用clear将全局变量设置为False;

下面使用一个两个玩家掷骰子,一个裁判判断胜负,共三轮的游戏来演示一下事件event的使用;

E = threading.Event()
E.clear()
res1, res2, cnt, lst = 0, 0, 3, ("player2", 'both', 'player1')

def show_round_res():
  print ("Stop! judging... %s win!" % lst[cmp(res1, res2) + 1])

def judge():
  global cnt 
  while cnt > 0:
    print 'start game!'
    E.set()
    time.sleep(1)
    E.clear()
    show_round_res()
    time.sleep(1)
    cnt -= 1
  print "game over by judge!"

def player1():
  global res1
  while cnt > 0:
    if E.is_set():
      res1 = random.randint(1, 6)
      print "player1 get %d" % res1
      time.sleep(1.5)
      E.wait()
  print "player1 quit!"

def player2():
  global res2
  while cnt > 0:
    if E.is_set():
      res2 = random.randint(1, 6)
      print "player2 get %d" % res2
      time.sleep(1.5)
      E.wait()
  print "player2 quit!"


if __name__ == "__main__":
  t1 = threading.Thread(target=judge, args=( ))
  t2 = threading.Thread(target=player1, args=( ))
  t3 = threading.Thread(target=player2, args=( ))
  t1.start()
  t2.start()
  t3.start()
  t1.join()
  E.set()

有一点需要注意的是,线程调用wait时,只有当变量值为False时才会阻塞当前线程,如果全局变量是True,会立即返回;

下面是一种可能的结果:

start game!
player1 get 2
player2 get 2
Stop! judging... both win!
start game!
player2 get 3
player1 get 4
Stop! judging... player1 win!
start game!
player1 get 1
player2 get 3
Stop! judging... player2 win!
game over by judge!
player2 quit!
player1 quit!

总结

上面是为了解决线程安全问题所采取的一些同步措施。Python为进程同步提供了类似线程的同步措施,例如锁、信号量等。

不同于线程间共享进程资源,进程拥有独立的地址空间,不同进程内存空间是隔离的。

因此对于进程我们通常关注他们之间的通信方式,后续会有文章介绍进程之间的同步。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python操作sqlite3快速、安全插入数据(防注入)的实例
Apr 26 Python
Python中的__SLOTS__属性使用示例
Feb 18 Python
python optparse模块使用实例
Apr 09 Python
深入讲解Python编程中的字符串
Oct 14 Python
探究python中open函数的使用
Mar 01 Python
python嵌套字典比较值与取值的实现示例
Nov 03 Python
详解Python3.6安装psutil模块和功能简介
May 30 Python
Python os.access()用法实例
Feb 18 Python
python实现的登录与提交表单数据功能示例
Sep 25 Python
利用python Selenium实现自动登陆京东签到领金币功能
Oct 31 Python
Python操作SQLite/MySQL/LMDB数据库的方法
Nov 07 Python
PyCharm中配置PySide2的图文教程
Jun 18 Python
pandas的to_datetime时间转换使用及学习心得
Aug 11 #Python
python中时间转换datetime和pd.to_datetime详析
Aug 11 #Python
Python时间序列缺失值的处理方法(日期缺失填充)
Aug 11 #Python
python3实现带多张图片、附件的邮件发送
Aug 10 #Python
python实现邮件自动发送
Aug 10 #Python
python爬取百度贴吧前1000页内容(requests库面向对象思想实现)
Aug 10 #Python
python正则爬取某段子网站前20页段子(request库)过程解析
Aug 10 #Python
You might like
了解咖啡雨林联盟认证 什么是雨林认证 雨林认证是什么意思
2021/03/05 新手入门
PHP imagecreatefrombmp 从BMP文件或URL新建一图像
2012/07/16 PHP
PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
2014/07/23 PHP
PHP中ID设置自增后不连续的原因分析及解决办法
2016/08/21 PHP
动态表单验证的操作方法和TP框架里面的ajax表单验证
2017/07/19 PHP
laravel 查询数据库获取结果实现判断是否为空
2019/10/24 PHP
用javascript实现改变TEXTAREA滚动条和按钮的颜色,以及怎样让滚动条变得扁平
2007/04/20 Javascript
ExtJs3.0中Store添加 baseParams 的Bug
2010/03/10 Javascript
javascript 使td内容不换行不撑开
2012/11/29 Javascript
javascript密码强度校验代码(两种方法)
2015/08/10 Javascript
js阻止浏览器默认行为的简单实例
2016/05/15 Javascript
JS返回只包含数字类型的数组实例分析
2016/12/16 Javascript
javascript实现的图片预览功能
2017/03/25 Javascript
jQuery实现select下拉框获取当前选中文本、值、索引
2017/05/08 jQuery
jQuery实现动态添加和删除input框实例代码
2019/03/26 jQuery
详解在Javascript中进行面向切面编程
2019/04/28 Javascript
解决Vue router-link绑定事件不生效的问题
2020/07/22 Javascript
[01:16:13]DOTA2-DPC中国联赛 正赛 SAG vs Dragon BO3 第一场 2月22日
2021/03/11 DOTA
用python实现的可以拷贝或剪切一个文件列表中的所有文件
2009/04/30 Python
python支持断点续传的多线程下载示例
2014/01/16 Python
python+mysql实现简单的web程序
2014/09/11 Python
Python对切片命名的实现方法
2018/10/16 Python
Python设计模式之装饰模式实例详解
2019/01/21 Python
Python利用 utf-8-sig 编码格式解决写入 csv 文件乱码问题
2020/02/21 Python
Python3如何判断三角形的类型
2020/04/12 Python
详解向scrapy中的spider传递参数的几种方法(2种)
2020/09/28 Python
python制作一个简单的gui 数据库查询界面
2020/11/19 Python
老海军美国官网:Old Navy
2016/09/05 全球购物
外语专业毕业生自我评价分享
2013/10/05 职场文书
工程造价与财务管理专业应届生求职信
2013/10/06 职场文书
优秀本科生求职推荐信
2014/02/24 职场文书
《金子》教学反思
2014/04/13 职场文书
家长学校工作方案
2014/05/07 职场文书
八荣八耻演讲稿
2014/09/15 职场文书
煤矿安全生产工作总结
2015/08/13 职场文书
教你使用Pandas直接核算Excel中快递费用
2021/05/12 Python