您的位置:

python中的线程同步(linux 线程同步)

本文目录一览:

PYTHON多线程同步的几种方法

Python进阶(二十六)-多线程实现同步的四种方式

临界资源即那些一次只能被一个线程访问的资源,典型例子就是打印机,它一次只能被一个程序用来执行打印功能,因为不能多个线程同时操作,而访问这部分资源的代码通常称之为临界区。

锁机制

threading的Lock类,用该类的acquire函数进行加锁,用realease函数进行解锁

import threadingimport timeclass Num:

def __init__(self):

self.num = 0

self.lock = threading.Lock() def add(self):

self.lock.acquire()#加锁,锁住相应的资源

self.num += 1

num = self.num

self.lock.release()#解锁,离开该资源

return num

n = Num()class jdThread(threading.Thread):

def __init__(self,item):

threading.Thread.__init__(self)

self.item = item def run(self):

time.sleep(2)

value = n.add()#将num加1,并输出原来的数据和+1之后的数据

print(self.item,value)for item in range(5):

t = jdThread(item)

t.start()

t.join()#使线程一个一个执行12345678910111213141516171819202122232425262728

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

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

信号量

信号量也提供acquire方法和release方法,每当调用acquire方法的时候,如果内部计数器大于0,则将其减1,如果内部计数器等于0,则会阻塞该线程,知道有线程调用了release方法将内部计数器更新到大于1位置。

import threadingimport timeclass Num:

def __init__(self):

self.num = 0

self.sem = threading.Semaphore(value = 3) #允许最多三个线程同时访问资源

def add(self):

self.sem.acquire()#内部计数器减1

self.num += 1

num = self.num

self.sem.release()#内部计数器加1

return num

n = Num()class jdThread(threading.Thread):

def __init__(self,item):

threading.Thread.__init__(self)

self.item = item def run(self):

time.sleep(2)

value = n.add()

print(self.item,value)for item in range(100):

python基础(21)-线程通信

到这里,我们要聊一下线程通信的内容;

首先,我们抛开语言不谈,先看看比较基础的东西,线程间通信的方式;其实也就是哪几种(我这里说的,是我的所谓的知道的。。。)事件,消息队列,信号量,条件变量(锁算不算?我只是认为是同步的一种);所以我们也就是要把这些掌握了,因为各有各的好处嘛;

条件变量我放到了上面的线程同步里面讲了,我总感觉这算是同步的一种,没有很多具体信息的沟通;同时吧,我认为条件变量比较重要,因为这种可以应用于线程池的操作上;所以比较重要;这里,抛开条件变量不谈,我们看看其他的东西;

1、消息队列:

queue 模块下提供了几个阻塞队列,这些队列主要用于实现线程通信。在 queue 模块下主要提供了三个类,分别代表三种队列,它们的主要区别就在于进队列、出队列的不同。

关于这三个队列类的简单介绍如下:

queue.Queue(maxsize=0):代表 FIFO(先进先出)的常规队列,maxsize 可以限制队列的大小。如果队列的大小达到队列的上限,就会加锁,再次加入元素时就会被阻塞,直到队列中的元素被消费。如果将 maxsize 设置为 0 或负数,则该队列的大小就是无限制的。

queue.LifoQueue(maxsize=0):代表 LIFO(后进先出)的队列,与 Queue 的区别就是出队列的顺序不同。

PriorityQueue(maxsize=0):代表优先级队列,优先级最小的元素先出队列。

这三个队列类的属性和方法基本相同, 它们都提供了如下属性和方法:

Queue.qsize():返回队列的实际大小,也就是该队列中包含几个元素。

Queue.empty():判断队列是否为空。

Queue.full():判断队列是否已满。

Queue.put(item, block=True, timeout=None):向队列中放入元素。如果队列己满,且 block 参数为 True(阻塞),当前线程被阻塞,timeout 指定阻塞时间,如果将 timeout 设置为 None,则代表一直阻塞,直到该队列的元素被消费;如果队列己满,且 block 参数为 False(不阻塞),则直接引发 queue.FULL 异常。

Queue.put_nowait(item):向队列中放入元素,不阻塞。相当于在上一个方法中将 block 参数设置为 False。

Queue.get(item, block=True, timeout=None):从队列中取出元素(消费元素)。如果队列已满,且 block 参数为 True(阻塞),当前线程被阻塞,timeout 指定阻塞时间,如果将 timeout 设置为 None,则代表一直阻塞,直到有元素被放入队列中; 如果队列己空,且 block 参数为 False(不阻塞),则直接引发 queue.EMPTY 异常。

Queue.get_nowait(item):从队列中取出元素,不阻塞。相当于在上一个方法中将 block 参数设置为 False。

其实我们想想,这个队列,是python进行封装的,那么我们可以用在线程间的通信;同时也是可以用做一个数据结构;先进先出就是队列,后进先出就是栈;我们用这个栈写个十进制转二进制的例子:

没毛病,可以正常的打印;其中需要注意的就是,maxsize在初始化的时候如果是0或者是个负数的话,那么就会是不限制大小;

那么其实我们想想,我们如果用做线程通信的话,我们两个线程,可以把队列设置为1的大小,如果是1对多,比如是创建者和消费者的关系,我们完全可以作为消息队列,比如说创建者一直在创建一些东西,然后放入到消息队列里面,然后供消费着使用;就是一个很好的例子;所以,其实说是消息队列,也就是队列,没差;

=====================================================================

下面来看一下事件

Event 是一种非常简单的线程通信机制,一个线程发出一个 Event,另一个线程可通过该 Event 被触发。

Event 本身管理一个内部旗标,程序可以通过 Event 的 set() 方法将该旗标设置为 True,也可以调用 clear() 方法将该旗标设置为 False。程序可以调用 wait() 方法来阻塞当前线程,直到 Event 的内部旗标被设置为 True。

Event 提供了如下方法:

is_set():该方法返回 Event 的内部旗标是否为True。

set():该方法将会把 Event 的内部旗标设置为 True,并唤醒所有处于等待状态的线程。

clear():该方法将 Event 的内部旗标设置为 False,通常接下来会调用 wait() 方法来阻塞当前线程。

wait(timeout=None):该方法会阻塞当前线程。

这里我想解释一下;其实对于事件来说,事件可以看成和条件变量是一样的,只是我们说说不一样的地方;

1、对于事件来说,一旦触发了事件,也就是说,一旦set为true了,那么就会一直为true,需要clear调内部的标志,才能继续wait;但是conditon不是,他是一次性的唤醒其他线程;

2、conditon自己带锁;事件呢?不是的;没有自己的锁;比如说有一个存钱的线程,有一个是取钱的线程;那么存钱的线程要存钱;需要怎么办呢?1、发现银行没有钱了(is_set判断);2、锁住银行;3、存钱;4、释放银行;5、唤醒事件;对于取钱的人;1、判断是否有钱;2、被唤醒了,然后锁住银行;3、开始取钱;4、清理告诉存钱的人,我没钱了(clear);5、释放锁;6、等着钱存进去;

其实说白了,就是记住一点;这个旗标需要自己clear就对了

写个例子,怕以后忘了怎么用;

其实时间和信号量比较像;但是信号量不用自己清除标志位;但是事件是需要的;

python 线程同步问题

class myThread (threading.Thread):

def __init__(self, threadID, name, counter):

threading.Thread.__init__(self)

self.threadID = threadID

self.name = name

self.counter = counter

def run(self):

print "Starting " + self.name

# 获得锁,成功获得锁定后返回True

# 可选的timeout参数不填时将一直阻塞直到获得锁定

# 否则超时后将返回False

threadLock.acquire()

print_time(self.name, self.counter, 3)

# 释放锁

threadLock.release()

def print_time(threadName, delay, counter):

while counter:

time.sleep(delay)

print "%s: %s" % (threadName, time.ctime(time.time()))

counter -= 1

threadLock = threading.Lock()

threads = []

# 创建新线程

thread1 = myThread(1, "Thread-1", 1)

thread2 = myThread(2, "Thread-2", 2)

# 开启新线程

thread1.start()

thread2.start()