1.共享变量
2.queue队列 - 它本身是安全的 - 引用了 deque 双端队列
import time
import threading
from queue import Queue
def get_data_html(queue):
# global data_list
while True:
url = queue.get()
print('开始获取数据html的时间')
time.sleep(2)
print('获取数据html结束的时间')
def get_data_url(queue):
# global data_list
while True:
print('开始获取数据url的时间')
time.sleep(3)
for item in range(30):
# 添加
queue.put('http://logic.org/{id}'.format(id=item))
print('获取数据url结束的时间')
if __name__ == '__main__':
# 设置队列
data_url_queue = Queue(maxsize=1000)
thread_url = threading.Thread(target=get_data_url,args=(data_url_queue,))
for item in range(10):
thread_html = threading.Thread(target=get_data_html,args=(data_url_queue,))
thread_html.start()
start_time = time.time()
# 成对出现的
data_url_queue.join()
data_url_queue.task_done()
# thread_url.start()
print("中间运行时间:{}".format(time.time()-start_time))
1.线程间的通讯问题
2.线程同步问题 - 为了解决结果不一致
'''
'''
import dis
def time(a):
a += 1
def test(a):
a -= 1
'''
0 LOAD_FAST 0 (a)
2 LOAD_CONST 1 (1)
4 INPLACE_ADD + 1
6 STORE_FAST 0 (a)
'''
print(dis.dis(time))
print(dis.dis(test))
Module_thread_lock.py
'''
A(a,b)
acquire(a)
acquire(b)
资源竞争 - 互相等待
B(a,b)
acquire(b)
acquire(a)
'''
from threading import Lock
a = 0
lock = Lock()
def time():
global a
global lock
for item in range(1000000):
# 上锁
lock.acquire()
a += 1
# 释放锁
lock.release()
def test():
global a
global lock
for item in range(1000000):
# 上锁
lock.acquire()
a -= 1
# 释放锁
lock.release()
import threading
thread_1 = threading.Thread(target=time)
thread_2 = threading.Thread(target=test)
thread_1.start()
thread_2.start()
thread_1.join()
thread_1.join()
print(a)
1.用锁会影响性能
2.锁会引起死锁 资源竞争 - 互相等待
RLock - 可重入锁
'''
# '''
# import dis
#
#
# def time(a):
# a += 1
#
#
# def test(a):
# a -= 1
# '''
# 0 LOAD_FAST 0 (a)
# 2 LOAD_CONST 1 (1)
# 4 INPLACE_ADD + 1
# 6 STORE_FAST 0 (a)
# '''
#
# print(dis.dis(time))
# print(dis.dis(test))
'''
A(a,b)
acquire(a)
acquire(b)
资源竞争 - 互相等待
B(a,b)
acquire(b)
acquire(a)
'''
from threading import Lock, RLock
a = 0
lock = RLock()
def time():
global a
global lock
for item in range(1000000):
# 上锁
lock.acquire()
# do_time(lock)
lock.acquire()
a += 1
# 释放锁
lock.release()
lock.release()
def do_time(lock):
# 上锁
lock.acquire()
# 0---------------------
# 释放锁
lock.release()
def test():
global a
global lock
for item in range(1000000):
# 上锁
lock.acquire()
a -= 1
# 释放锁
lock.release()
import threading
thread_1 = threading.Thread(target=time)
thread_2 = threading.Thread(target=test)
thread_1.start()
thread_2.start()
thread_1.join()
thread_1.join()
print(a)
通过condition完成双方协同聊天的功能
条件变量 主要用于复杂线程间的同步:
在调用with cond 之后才能调用 wait 和 notify方法
在condition 有2层锁, 一把底层锁会在线程调用wait方法的时候释放,上面的锁会在每次调用wait的时候分配一把并放入cond中的等待队列中;直到notify方法的唤醒。
import threading
from threading import Condition
'''
张三 : 你好,很高兴认识你 A
马六 : 我也是 B
张三 : 你是什么样的人
马六 : 我是憨憨
张三 : 。。。
马六 : 。。。。。。
'''
class ZhangSan(threading.Thread):
def __init__(self, lock):
super().__init__(name='张三')
self.lock = lock
def run(self):
lock.acquire()
print("{} : 你好,很高兴认识你".format(self.name))
lock.release()
# lock.acquire()
# print("{} : 你是什么样的人".format(self.name))
# lock.release()
class MaLiu(threading.Thread):
def __init__(self, lock):
self.lock = lock
super().__init__(name='马六')
def run(self):
lock.acquire()
print("{} : 我也是".format(self.name))
lock.release()
# lock.acquire()
# print("{} : 我是憨憨".format(self.name))
# lock.release()
if __name__ == '__main__':
lock = threading.Lock()
zhang_san = ZhangSan(lock)
ma_liu = MaLiu(lock)
zhang_san.start()
ma_liu.start()
Condition
import threading
from threading import Condition
'''
张三 : 你好,很高兴认识你 A
马六 : 我也是 B
张三 : 你是什么样的人
马六 : 我是憨憨
张三 : 。。。
马六 : 。。。。。。
'''
class ZhangSan(threading.Thread):
def __init__(self, cond):
super().__init__(name='张三')
self.cond = cond
def run(self):
with self.cond:
# self.cond.acquire()
print("{} : 你好,很高兴认识你".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 你是什么样的人".format(self.name))
self.cond.notify()
self.cond.wait()
# self.cond.release()
class MaLiu(threading.Thread):
def __init__(self, cond):
self.cond = cond
super().__init__(name='马六')
def run(self):
with self.cond:
# self.cond.acquire()
self.cond.wait()
print("{} : 我也是".format(self.name))
self.cond.notify()
self.cond.wait()
print("{} : 我是憨憨".format(self.name))
self.cond.notify()
# self.cond.release()
if __name__ == '__main__':
cond = threading.Condition()
zhang_san = ZhangSan(cond)
ma_liu = MaLiu(cond)
# 程序的执行顺序
ma_liu.start()
zhang_san.start()
'''
读和写
Semaphroe():用于控制进入的数量的锁, 信号量
'''
import threading
# threading.Semaphore()
import time
class GetUrl(threading.Thread):
def __init__(self, sem):
super().__init__()
self.sem = sem
def run(self):
# list.append()
for item in range(20):
# 上锁
self.sem.acquire()
html_thread = HtmlSpider('http://news.baidu.com/{}'.format(item), self.sem)
html_thread.start()
class HtmlSpider(threading.Thread):
def __init__(self, url, sem):
super().__init__()
self.url = url
self.sem = sem
def run(self):
time.sleep(2)
print("获取了一页html详情信息!")
# 释放锁
self.sem.release()
if __name__ == '__main__':
# 只允许并发3个
sem = threading.Semaphore(3)
url_threads = GetUrl(sem)
url_threads.start()