线程特定数据的引出
单线程C程序有两类基本数据:局部数据和全局数据。
对于多线程C程序,添加了第三类数据:线程特定数据
那么为什么要引入线程特定数据呢?
试想如果你的一个线程里面嵌套调用了很多函数,而你又想在这些函数之间使用一个公共的变量,如果在单线程C中,我们是不是就要声明一个全局变量了呢?
是的。但是我们想使声明的这个全局变量只属于我们当前这个实例线程(同一个void *(*start_routine)(void *)可以实例化很多线程),其他的线程访问不到,故引入线程特定数据TSD。(ps:如果我们直接声明了一个全局变量,则其他线程也有可能使用到这个变量)。
线程特定数据的概念:
线程特定数据与全局数据非常相似,区别在于前者为线程所有。
(如果你学过面向对象编程,他们的关系就类似于class中静态成员与普通成员的关系。
所有对象都可以访问静态成员,而每个普通对象的普通成员只能被自己这个对象访问)
线程特定数据与python
通过查阅相关资料,博主我基于_thread_实现的threading官方文档,模块是python是实现多线程的内置库。
在官方文档的目录中,看到一级目录的Thread-Local Data。
**Thread-local data is data whose values are thread specific.
线程本地数据的值是线程特有的
**For more details and extensive examples, see the documentation string of the. threading local module.
更多的细节和例子,请到=查看_threading_ local模块的字符文档
基于python的threading内置库的14-5实验的实现–使用_threading_ local
客户端程序
#client_c.py
import socket
import time
import queue
from threading import Thread
q = queue.Queue()
def recv_message(s):
data = s.recv(1024).decode('utf-8').strip()
print(data)
Cli_name=input('Input your name:')
s.send(Cli_name.encode('utf-8'))
while True:
data = input('\ninput Message:')
s.send(data.encode('utf-8'))
if data == 'exit':
q.put(1)
break
data = s.recv(1024).decode('utf-8').strip()
print(data)
s.close()
try:
s = socket.create_connection(('127.0.0.1', 12306))
#recv_message(s)
Thread(target=recv_message, args=(s,)).start()
time.sleep(1)
while q.empty():
pass
except Exception as e:
print(e)
服务端程序
import socket
from threading import Thread
import socketserver
import threading
from threading import get_ident
HOST = ''
POST = 12306
BUFSIZ = 1024
ADDR = (HOST, POST)
cli_data = threading.local() #实例化线程本地数据对象
def message_handle(client):
cli_data_ls=[]
client.send('Server Message: Welcome to my server'.encode('utf-8'))
cli_name = client.recv(1024).decode('utf-8')
print('You got a connection from %s. Client name is %s'%(addr,cli_name))
while True:
data = client.recv(1024).decode('utf-8')
#cli_data.msg=data
#items=cli_data.msg
#cli_data_ls.append(items)
cli_data_ls.append(data) #python语言实现14-5实现的效果并不一定要用到python中的线程本地数据,python中使用列表即可存储用户历史信息,但该列表是不是TSD,还有待实验验证
print('Recieve Client (%s) Message: %s'%(cli_name,data))
if data == 'exit':
g_conn_pool.remove(client)
client.send(data.encode('utf-8'))
#print(cli_name+'下线了'+str(get_ident()),end='')
cli_data.msg=cli_data_ls #使用python中的线程本地数据对象 存储该线程的数据,其他线程无法访问该数据,但对该线程的所有函数是可访问的
print(cli_data_ls)
print(cli_data.msg)
print(cli_data.__dict__)
break
data='Server Message:'+data[::-1]
client.send(data.encode('utf-8'))
g_socket = None
g_conn_pool = []
try:
g_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #创建SOCKET
g_socket.bind(ADDR)
g_socket.listen(5) #参数5是侦听次数
while True:
client, addr = g_socket.accept()
#print(addr)
g_conn_pool.append(client) #存储链接服务器的客户端的数量
#message_handle(client)
t = Thread(target=message_handle, args=(client,)) #实例化线程对象,参数target=message_handle表明该线程运行函数message_handle
t.setDaemon(True)
t.start()
except Exception as e:
print(e)
print('exit')
服务端核心代码
函数主体中
t = Thread(target=message_handle, args=(client,)) #实例化线程对象,参数target=message_handle表明该线程运行函数message_handle
t.setDaemon(True)
t.start()
该代码初始引入了threading库中的Thread类,from threading import Thread
使用该类Thread
可以实例化线程对象,参数target=message_handle表明该线程运行函数message_handle
message_handle 函数中
cli_data_ls.append(data) #python语言实现14-5实现的效果并不一定要用到python中的线程本地数据,python中使用列表即可存储用户历史信息,但该列表是不是TSD,还有待实验验证
cli_data.msg=cli_data_ls #使用python中的线程本地数据对象 存储该线程的数据,其他线程无法访问该数据,但对该线程的所有函数是可访问的