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基于DES算法加密解密实例
Jun 03 Python
python实现汉诺塔递归算法经典案例
Mar 01 Python
python访问抓取网页常用命令总结
Apr 11 Python
Python脚本按照当前日期创建多级目录
Mar 01 Python
详解pandas如何去掉、过滤数据集中的某些值或者某些行?
May 15 Python
Django框架之DRF 基于mixins来封装的视图详解
Jul 23 Python
Django对接支付宝实现支付宝充值金币功能示例
Dec 17 Python
Pytorch在dataloader类中设置shuffle的随机数种子方式
Jan 14 Python
Python脚本实现监听服务器的思路代码详解
May 28 Python
Python猫眼电影最近上映的电影票房信息
Sep 18 Python
装上这 14 个插件后,PyCharm 真的是无敌的存在
Jan 11 Python
python实现黄金分割法的示例代码
Apr 28 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 常用字符串函数总结
2008/03/15 PHP
如何给phpcms v9增加类似于phpcms 2008中的关键词表
2013/07/01 PHP
ThinkPHP独立分组使用的注意事项
2014/11/25 PHP
php设计模式之单例模式代码
2016/06/11 PHP
PHP创建XML的方法示例【基于DOMDocument类及SimpleXMLElement类】
2019/09/10 PHP
PHP7修改的函数
2021/03/09 PHP
JavaScript入门教程 Cookies
2009/01/31 Javascript
XHTML下,JS浮动代码失效的问题
2009/11/12 Javascript
javascript 哈希表(hashtable)的简单实现
2010/01/20 Javascript
JavaScript中的onerror事件概述及使用
2013/04/01 Javascript
Javascript/Jquery——简单定时器的多种实现方法
2013/07/03 Javascript
jQuery实现在textarea指定位置插入字符或表情的方法
2015/03/11 Javascript
jQuery移动端图片上传组件
2016/06/12 Javascript
聊一聊JS中this的指向问题
2016/06/17 Javascript
如何获取元素的最终background-color
2017/02/06 Javascript
jQuery实现在新增加的元素上添加事件方法案例分析
2017/02/09 Javascript
nodejs基于mssql模块连接sqlserver数据库的简单封装操作示例
2018/01/05 NodeJs
jQuery实现form表单序列化转换为json对象功能示例
2018/05/23 jQuery
JavaScript 下载svg图片为png格式
2018/06/21 Javascript
开发Node CLI构建微信小程序脚手架的示例
2020/03/27 Javascript
从Python的源码来解析Python下的freeblock
2015/05/11 Python
Python如何为图片添加水印
2016/11/25 Python
pandas中的DataFrame按指定顺序输出所有列的方法
2018/04/10 Python
python 删除非空文件夹的实例
2018/04/26 Python
Python中循环后使用list.append()数据被覆盖问题的解决
2018/07/01 Python
Python安装pycurl失败的解决方法
2018/10/15 Python
python实现H2O中的随机森林算法介绍及其项目实战
2019/08/29 Python
基于Python生成个性二维码过程详解
2020/03/05 Python
eDreams巴西:廉价机票,酒店优惠和度假套餐
2017/04/14 全球购物
美国批发供应商:Kole Imports
2019/04/10 全球购物
使用C#编写创建一个线程的代码
2013/01/22 面试题
应届毕业生求职信
2014/05/26 职场文书
校庆口号
2014/06/20 职场文书
单位法定代表人授权委托书
2014/09/20 职场文书
Windows Server 2012 修改远程默认端口3389的方法
2022/04/28 Servers
Oracle删除归档日志及添加定时任务
2022/06/28 Oracle