Heim > Fragen und Antworten > Hauptteil
Ich habe viele Artikel online gelesen und bin immer noch verwirrt. Kann mir jemand diese beiden Konzepte leicht verständlich erklären?
Bei der Python-Multithread-Codierung verwende ich normalerweise eine while-True-Endlosschleife in der Ausführungsmethode des Threads, rufe dann queue.task_done am Ende des Schleifenkörpers der Endlosschleife auf, um die Warteschlange zu entfernen, und rufe dann die Warteschlange auf Join-Methode im Hauptthread zum Blockieren des Hauptthreads. Ist diese Multithread-Codierungsmethode sinnvoll? Wird es Fehler geben? Außerdem möchte ich fragen, ob die Endlosschleife, die ich in run aufrufe, als Spin-Lock bezeichnet wird.
高洛峰2017-06-14 10:53:20
首先要了解什么是互斥锁,互斥锁代表的意思是什么,
就是在两个线程A,B 访问同一块内存的时侯。
理想情况下我们的执行顺序应该是 A 完全执行完后,B来执行
但是,执行是有占用CPU指令时间的,如果不用任何机制的话,当A执行到一半时,B占用了CPU,B去处理这段内存,然后B执行完毕,A再得到CPU,内存数据不就出错了吗?
为了内存的数据安全。就采用了一种互斥的技术,A访问这段内存的时候,首先判断这段内存有没有在使用中的标志(取个名字叫做锁),没有的话对这段内存加一个标志(锁),然后A在处理这段内存,A处理完了解锁。如果在A处理内存这个时候B来访问的话,B看到这段内存有使用中的标志(锁)了,B可以有好几种行为。行为一:占用CPU。不断循环并测试锁的状态,线程不会挂起(睡眠),处于忙等状态,采用这种行为的锁叫做自旋锁。行为二:线程B休眠阻塞,放弃CPU,直到A执行完了,锁没了,再使用内存。这种行为叫做互斥锁。看到这里你大概也明白了,锁就是实现互斥作用的同步机制。自旋锁就是互斥锁的一种情况(等待的时候会占用CPU的互斥锁)罢了。
不要被名称所误导。要了解背后的机制,换个名字也要明白,
参考链接 链接描述
过去多啦不再A梦2017-06-14 10:53:20
1.Python多线程run方法的中使用while循环时,如果在循环体没有使用停止程序机制,会一直运行下去.因此楼主如果想让编码方式得当,可以使用信号量或者其他变量机制通知循环体停止,或者判断队列是否为空,若为空,直接break,退出循环.
2.run中的死循环不是自旋锁,假如循环体内有资源竞争,给加了个锁,但这种锁也是互斥锁.
python的锁使用的是信号量semaphore,不是spinlock.
// https://svn.python.org/projects/python/trunk/Python/thread_atheos.h
static int fastmutex_lock(fastmutex_t * mutex)
{
atomic_t prev = atomic_add(&mutex->count, 1);
if (prev > 0)
return lock_semaphore(mutex->sem);
return 0;
}
自旋锁:多线程同时访问同一个资源,为防止资源的读取修改不一致设置的一种锁,如果线程访问资源时,已经有线程占有资源,那么后者线程会等待当前线程释放资源,此时后者(不休眠)一直运行CPU检测前者占有资源是否释放,这种后者访问并一直检测资源占有的机制就是自旋锁.
互斥锁:目的和自旋锁一样,但机制不一样,当线程占用资源后,加上锁,后者线程访问时,由于资源被占有,转入休眠(sleep)状态,等资源被释放后,通过信号量通知排队等候的线程。
过去多啦不再A梦2017-06-14 10:53:20
Python代码会按照这样的流程进行运行,
设置GIL
切换到某一个线程
运行
线程退出,设置为休眠状态
解锁GIL
重复以上操作
可能是因为GIL的原因,我似乎没有在Python里面看到过自旋锁,更多使用的是互斥锁。
下面是我以前写多线程的方法,仅供参考~
import Queue
from threading import Thread
temp_queue = Queue.Queue()
class Test(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
while temp_queue.empty() is False:
pass
# do sth here
# temp = temp_queue.get()
tasks = []
for i in range(10):
tasks.append(Test())
for task in tasks:
task.start()
for task in tasks:
task.join()
既然是队列,Queue中Queue().get()中说明了Remove and return an item from the queue.