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 相关文章推荐
django轻松使用富文本编辑器CKEditor的方法
Mar 30 Python
Python判断文件或文件夹是否存在的三种方法
Jul 27 Python
python2.7实现FTP文件下载功能
Apr 15 Python
用Python写一段用户登录的程序代码
Apr 22 Python
Python3 利用requests 库进行post携带账号密码请求数据的方法
Oct 26 Python
python调用并链接MATLAB脚本详解
Jul 05 Python
vscode 配置 python3开发环境的方法
Sep 19 Python
python应用文件读取与登录注册功能
Sep 23 Python
python批量将excel内容进行翻译写入功能
Oct 10 Python
在PyCharm中实现添加快捷模块
Feb 12 Python
聊聊python中的异常嵌套
Sep 01 Python
Python的轻量级ORM框架peewee使用教程
Feb 05 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
PHP类继承 extends使用介绍
2014/01/14 PHP
thinkPHP通用控制器实现方法示例
2017/11/23 PHP
laravel框架实现为 Blade 模板引擎添加新文件扩展名操作示例
2020/01/25 PHP
jQuery EasyUI 中文API Button使用实例
2010/04/14 Javascript
Jquery Change与bind事件代码
2011/09/29 Javascript
node.js中的console.trace方法使用说明
2014/12/09 Javascript
node.js中的events.emitter.once方法使用说明
2014/12/10 Javascript
javascript html5实现表单验证
2016/03/01 Javascript
Bootstrap基本组件学习笔记之面板(14)
2016/12/08 Javascript
js获取一组日期中最近连续的天数
2017/05/25 Javascript
jQuery 循环遍历改变a标签的href(实例讲解)
2017/07/12 jQuery
JS库中的Particles.js在vue上的运用案例分析
2017/09/13 Javascript
React降级配置及Ant Design配置详解
2018/12/27 Javascript
js删除数组中某几项的方法总结
2019/01/16 Javascript
如何解决.vue文件url引用文件的问题
2019/01/18 Javascript
Vue插件之滑动验证码
2019/09/21 Javascript
JS快速实现简单计算器
2020/04/08 Javascript
python实现登陆知乎获得个人收藏并保存为word文件
2015/03/16 Python
Python实现感知器模型、两层神经网络
2017/12/19 Python
python实现装饰器、描述符
2018/02/28 Python
Python中max函数用于二维列表的实例
2018/04/03 Python
python 使用turtule绘制递归图形(螺旋、二叉树、谢尔宾斯基三角形)
2019/05/30 Python
python2使用bs4爬取腾讯社招过程解析
2019/08/14 Python
Python selenium页面加载慢超时的解决方案
2020/03/18 Python
浅谈TensorFlow之稀疏张量表示
2020/06/30 Python
深入浅析Python代码规范性检测
2020/07/31 Python
Selenium 配置启动项参数的方法
2020/12/04 Python
使用 css3 transform 属性来变换背景图的方法
2019/05/07 HTML / CSS
快速实现一个简单的canvas迷宫游戏的示例
2018/07/04 HTML / CSS
Lucene推荐的分页方式是什么?
2015/12/07 面试题
节约粮食标语
2014/06/18 职场文书
小学雷锋月活动总结
2014/07/03 职场文书
岗位竞聘报告范文
2014/11/06 职场文书
业务内勤岗位职责
2015/04/13 职场文书
安全温馨提示语大全
2015/07/14 职场文书
python字典的元素访问实例详解
2021/07/21 Python