使用互斥锁同步线程

例子:有一个全局的计数num,每个线程获取这个全局的计数,根据num进行一些处理,然后将num加1。很容易写出这样的代码:

# encoding: UTF-8

import threading

impor time

class MyThread(threading.Thread):

        def run(self):

              global num

              time.sleep(1)

              num=num+1

              msg=self.name+' set num to '+str(num)

              print msg

num=0

def test():

       for i in range(5):

              t=MyThread()

              t.start()

if__name__=='__main__':

        test()

但是运行结果是不正确的:

Thread-5 set num to 2

Thread-3 set num to 3

Thread-2 set num to 5

Thread-1 set num to 5

Thread-4 set num to 4

问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期。这种现象称为“线程不安全”。

互斥锁同步

上面的例子引出了多线程编程的最常见问题:数据共享。当多个线程都修改某一个共享数据的时候,需要进行同步控制。

线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

threading模块中定义了Lock类,可以方便的处理锁定:

#创建锁

mutex = threading.Lock()

#锁定

mutex.acquire([timeout])

#释放

mutex.release()

其中,锁定方法acquire可以有一个超时时间的可选参数timeout。如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁,从而可以进行一些其他的处理。

使用互斥锁实现上面的例子的代码如下:

import threading

import time

class MyThread(threading.Thread):

       def run(self):

             global num

             time.sleep(1)

             if mutex.acquire(1):

                    num=num+1

                    msg=self.name+' set num to '+str(num)

                    print msg

                    mutex.release()

num=0

mutex=threading.Lock()

def test():

         for i in range(5):

              t=MyThread()

              t.start()

if__name__=='__main__':

       test()

运行结果:

Thread-3 set num to 1

Thread-4 set num to 2

Thread-5 set num to 3

Thread-2 set num to 4

Thread-1 set num to 5

可以看到,加入互斥锁后,运行结果与预期相符。

同步阻塞

当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“同步阻塞”(参见多线程的基本概念)。

直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 结果 : 互斥锁同步 上面的例子引出了多线程编程的最常见问题:数据共享。当多个线程都修改某一个共享数据的时候,需要...
    大富帅阅读 9,552评论 3 12
  • 1.进程和线程 队列:1、进程之间的通信: q = multiprocessing.Queue()2、...
    一只写程序的猿阅读 4,808评论 0 17
  • 线程 1.同步概念 1.多线程开发可能遇到的问题 同步不是一起的意思,是协同步调 假设两个线程t1和t2都要对nu...
    TENG书阅读 3,795评论 0 1
  • 线程 引言&动机 考虑一下这个场景,我们有10000条数据需要处理,处理每条数据需要花费1秒,但读取数据只需要0....
    不浪漫的浪漫_ea03阅读 2,895评论 0 0
  • 一.丢失的记忆 突然发现,关于小时候的事情,自己竟然没有丝毫的记忆,是因为过得毫无意义,还是自己天然呆萌,总...
    一只特立独行的猪_566e阅读 2,635评论 0 0