关于 Python 的线程锁, Python 线程 lock.release() 优先被当前线程 acquire 么?

2017-06-30 16:18:47 +08:00
 moxiaowei

import threading

import time

balance = 0

lock = threading.Lock()

def run_thread(n): global balance

for i in range(100):

    lock.acquire()

    balance = balance + 1

    n = n + balance

    time.sleep(1)

    print(threading.current_thread().name)

    print(n)

    print("\r\n\r\n")

    lock.release()

t1 = threading.Thread(target=run_thread, args=(5, ), name="t1")

t2 = threading.Thread(target=run_thread, args=(8, ), name="t2")

t1.start()

t2.start()

t1.join()

t2.join()

print(balance)

执行结果: t1 4661

t1 4758

t1 4856

t1 4955

t1 5055 -------------------这儿是 t1 线程已经执行完毕了

t2 109---------------------t2 线程开始执行了

t2 211

t2 314

t1 线程全部走完才会走 t2 线程

2684 次点击
所在节点    Python
26 条回复
dbow
2017-06-30 22:48:48 +08:00
@davinci 释放不了, 需要主动写代码释放, 典型的模式是在阻塞之前释放线程锁, 阻塞操作结束后重新取得。
以 time.sleep()里的这段代码为例,
Py_BEGIN_ALLOW_THREADS
rc = WaitForSingleObjectEx(hInterruptEvent, ul_millis, FALSE);
Py_END_ALLOW_THREADS
wwqgtxx
2017-06-30 23:36:23 +08:00
@dbow 但是在 Python 层面上看,所有会导致阻塞的系统库操作都会让 Python 解析器释放 GIL 锁
dbow
2017-06-30 23:54:28 +08:00
@wwqgtxx 是的, 主动释放的, 方法就是下面的, 在底层 C 代码释放的。
Py_BEGIN_ALLOW_THREADS
rc = WaitForSingleObjectEx(hInterruptEvent, ul_millis, FALSE);
Py_END_ALLOW_THREADS
wwqgtxx
2017-07-01 00:18:10 +08:00
@dbow 我现在就在想在直接用 ctypes 调用 c 类库的时候有没有什么办法可释放掉 GIL,因为有些时候并不想为了调用一个简单的 C 类库而去用 CPYTHON C API 写个封装,而 cytpes 类库默认应该是没有释放 GIL 的,所以会导致在一些耗时的操作上限制了多线程能力的发挥
dbow
2017-07-01 10:46:35 +08:00
@wwqgtxx ctypes 调用 c 函数是自动释放 GIL 的, 除非是调用 python 自己的 C API.

821 #ifdef WITH_THREAD
822 if ((flags & FUNCFLAG_PYTHONAPI) == 0)
823 Py_UNBLOCK_THREADS
824 #endif
825 if (flags & FUNCFLAG_USE_ERRNO) {
826 int temp = space[0];
827 space[0] = errno;
828 errno = temp;
829 }
830 #ifdef MS_WIN32
831 if (flags & FUNCFLAG_USE_LASTERROR) {
832 int temp = space[1];
833 space[1] = GetLastError();
834 SetLastError(temp);
835 }
wwqgtxx
2017-07-01 15:10:55 +08:00
@dbow 这一段我还真的没有仔细看过,可能是很久前某一篇错误的资料上说他不会自己释放吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/372192

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX