I have a single Python process which is using a serial port (unique resource) which is managed using an instance of a class A. There exists two different threads initialized using instances of classes B and C, which are constantly using the serial port resource through the objected already created.
import threading
Class A(threading.Thread):
#Zigbee serial port h开发者_开发百科andler
def __init__(self,dev):
#something here that initialize serial port
def run():
while True:
#listening serial interface
def pack(self):
#something
def checksum(self):
#something
def write(self):
#something
Class B(threading.Thread):
def __init__(self,SerialPortHandler):
self.serialporthandler=SerialPortHandler
def run(self)
while True:
#something that uses self.serialporthandler
Class C(threading.Thread):
def __init__(self,SerialPortHandler):
self.serialporthandler=SerialPortHandler
def run(self)
while True:
#something that uses self.serialporthandler
def main():
a=A('/dev/ttyUSB1')
b=B(a)
b.start()
c=C(a)
c.start()
if __name__=='main':
while True:
main()
The problem is that both threads are trying to access the serial resource at the same time. I could use several instances of the same class A, attaching Lock.acquire() and Lock.release() in the sensitive parts.
Could some of you point me to the right way?
Thank you in advance.
While you could share the serial port using appropriate locking, I wouldn't recommend it. I've written several multi-threaded applications that communicate on the serial port in Python, and in my experience the following approach is better:
- Have a single class, in a single thread, manage the actual serial port communication, via a
Queue
object or two:- Stuff read from the port is placed into the queue
- Commands to send to the port are placed into the queue and the "Serial thread" sends them
- Have the other threads implement logic by placing things into the queue and taking things out
Using Queue
objects will greatly simplify your code and make it more robust.
This approach opens a lot of possibilities for you in terms of design. You can, for example, register events (callbacks) with the serial thread manager and have it call them (in a synchronized way) when interesting events occur, etc.
Add a threading.Lock()
to class A
and make it acquire the lock when using it:
def __init__(self,dev):
self.lock = threading.Lock()
def read(self):
self.lock.acquire()
data = ? #whatever you need to do here to read
self.lock.release()
return data
def write(self, data):
self.lock.acquire()
#whatever you need to do to write
self.lock.release()
精彩评论