进程之间通信与线程同步是一个历久弥新的话题,对编程稍有了解应该都知道,但是细说又说不清。一方面除了工作中可能用的比较少,另一方面就是这些概念牵涉到的东西比较多,而且相对较深。网络编程,服务端编程,并发应用等都会涉及到。其开发和调试过程都不直观。由于同步通信机制的原理都是相通的,本文希通过望借助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的写不是原子操作,线程在写的过程中被打断,然后切换线程执行,回来时会继续执行被打断的写操作,不过可能覆盖掉这段时间另一个线程写的结果。

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

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

如果在读取数据之后,计算过程或者写回数据前被打断,当再次执行时,即使内存中的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 = ('',))
t2 = threading.Thread(target = tstart, args = ('',))
t1.start()
t2.start()
t1.join()
t2.join()
print res, len(res)
print 'share_data result:', share_data

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

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

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

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

这里有一点不好理解,当前线程修改了条件之后,通过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多线程同步实例分析的更多相关文章

  1. python多线程同步

    python多线程同步 作者:vpoet 日期:大约在夏季 import threading import time mylock = threading.RLock() num=0 class my ...

  2. Python正则简单实例分析

    Python正则简单实例分析 本文实例讲述了Python正则简单用法.分享给大家供大家参考,具体如下: 悄悄打入公司内部UED的一个Python爱好者小众群,前两天一位牛人发了条消息: 小的测试题:  ...

  3. 第十五章、Python多线程同步锁,死锁和递归锁

    目录 第十五章.Python多线程同步锁,死锁和递归锁 1. 引子: 2.同步锁 3.死锁 引子: 4.递归锁RLock 原理: 不多说,放代码 总结: 5. 大总结 第十五章.Python多线程同步 ...

  4. Python 多线程同步队列模型

    Python 多线程同步队列模型 我面临的问题是有个非常慢的处理逻辑(比如分词.句法),有大量的语料,想用多线程来处理. 这一个过程可以抽象成一个叫“同步队列”的模型. 具体来讲,有一个生产者(Dis ...

  5. Python多线程同步命令行模拟进度显示

    最近在一个Python(3.5)的小项目中需要用到多线程加快处理速度,同时需要显示进度,于是查了些资料找到几个实现方法:线程池的map-reduce和Queue结合线程的实现.这里简单的实例介绍一下Q ...

  6. python多线程同步机制Semaphore

    #!/usr/bin/env python # -*- coding: utf-8 -*- """ Python 线程同步机制:Semaphore "" ...

  7. [转]python 多线程threading简单分析

    多线程和多进程是什么自行google补脑 对于python 多线程的理解,我花了很长时间,搜索的大部份文章都不够通俗易懂.所以,这里力图用简单的例子,让你对多线程有个初步的认识. 单线程 在好些年前的 ...

  8. python多进程通信实例分析

    操作系统会为每一个创建的进程分配一个独立的地址空间,不同进程的地址空间是完全隔离的,因此如果不加其他的措施,他们完全感觉不到彼此的存在.那么进程之间怎么进行通信?他们之间的关联是怎样的?实现原理是什么 ...

  9. Python多线程同步互斥锁

    接着上篇多线程继续讲,上篇最后的多线程共享全局变量对变量的处理值出错在本文中给出解决方案. 出现这个情况的原因是在python解释器中GIL全局解释器锁. GIL:全局解释器锁,每个线程在执行的过程都 ...

随机推荐

  1. BZOJ 1483:[HNOI2009]梦幻布丁(链表启发式合并)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1483 题意:中文. 思路:对于每一种颜色,用一个链表串起来,一开始保存一个答案,后面颜色替换的时候再 ...

  2. HDU 6011:Lotus and Characters(贪心)

    http://acm.hdu.edu.cn/showproblem.php?pid=6011 题意:共有n种字符,每种字符有一个val和一个cnt,代表这个字符的价值和数量.可以制造的总价值是:第一个 ...

  3. .NET Core 3.0之深入源码理解Kestrel的集成与应用(二)

      前言 前一篇文章主要介绍了.NET Core继承Kestrel的目的.运行方式以及相关的使用,接下来将进一步从源码角度探讨.NET Core 3.0中关于Kestrel的其他内容,该部分内容,我们 ...

  4. 从无到有构建vue实战项目(五)

    八.错误总结(一) webpack打包项目识别子组件路径问题 之所以出现了这样的问题是因为在webpack打包项目时,未将此处的子组件路径正确识别: 将此处的carousel改为carousel.vu ...

  5. Django rest framework(1)----认证

    目录 Django组件库之(一) APIView源码 Django restframework   (1)  ----认证 Django rest framework(2)----权限 Django ...

  6. [HNOI2015]菜肴制作 题解(自带口胡证明)

    [HNOI2015]菜肴制作 时间限制: 1 Sec  内存限制: 512 MB 题目描述 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为 ...

  7. J2EE:Servlet上传文件到服务器,并相应显示

    Servlet 可以与HTML一起使用来允许用户上传文件到服务器 编辑上传文件的页面upload.html 注意事项:上传方式使用POST不能使用GET(GET不能上传文件) 表单 enctype 属 ...

  8. 学习2:内容# 1.while # 2.字符串格式化 # 3.运算符 # 4.编码初始

    目录 1.while循环 2.字符串格式化 3.运算符 4.编码初始 1.while循环 while -- 关键字 (死循环) if 条件: 结果 while 条件: 循环体 while True: ...

  9. linux 定时任务 crontabs 安装及使用方法

    boom 安装 crontab yum install crontabs centos7 自带了我没有手动去装 启动/关闭 service crond start // 启动服务 service cr ...

  10. 洛谷 P3367 并查集 【模板题】

    题目描述 如题,现在有一个并查集,你需要完成合并和查询操作. 输入输出格式 输入格式: 第一行包含两个整数N.M,表示共有N个元素和M个操作. 接下来M行,每行包含三个整数Zi.Xi.Yi 当Zi=1 ...