21.python线程

在这里插入图片描述
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体。程序是指令、数据及其组织形式的描述,进程是程序的实体。

Threads share the address space of the process that created it; processes have their own address space.
线程的地址空间共享,每个进程有自己的地址空间。
Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.
一个进程中的线程直接接入他的进程的数据段,但是每个进程都有他们自己的从父进程拷贝过来的数据段
Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
一个进程内部的线程之间能够直接通信,进程之间必须使用进程间通信实现通信
New threads are easily created; new processes require duplication of the parent process.
新的线程很容易被创建,新的进程需要从父进程复制
Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
一个进程中的线程间能够有相当大的控制力度,进程仅仅只能控制他的子进程
Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.
改变主线程(删除,优先级改变等)可能影响这个进程中的其他线程;修改父进程不会影响子进程

在这里插入图片描述
创建线程

def Cycle_number5():
    for number in range(5):
        print(number)
        time.sleep(1)
def Cycle_number10():
    for number in range(10):
        print(number)
        time.sleep(1)
def start_thread():
    thread1 = threading.Thread(target=Cycle_number5)
    thread2 = threading.Thread(target=Cycle_number10)
    thread1.start()
    thread2.start()
    print(threading.enumerate())

在这里插入图片描述
通过类创建线程,修改类中的run函数

class new_Thread(threading.Thread):
    def run(self):
        for i in range(3):
            time.sleep(1)
            msg = "I'm" + self.name + '@' + str(i)
            print(msg)
            self.print_name()
    def print_name(self):
        time.sleep(1)
        print(self.name)
instance1 = new_Thread()
instance2 = new_Thread()
instance1.start()
instance2.start()

在这里插入图片描述
在函数里声明全局变量,来改变变量值

number = 100
numbers = [11, 22]
def add100():
    global number
    number += 100
def add10():
    global number
    number += 10
def append33():
    numbers.append(33)
print (number)
print (numbers)
add100()
add10()
append33()
print (number)
print (numbers)

多线程共用全局变量

global_number = 100

def add1():
    global global_number
    global_number += 1
    print("global_number = %d" %global_number)
def add2():
    global global_number
    global_number += 2
    print('global_number = %d' %global_number)
def add3():
    global global_number
    global_number += 3
    print('global_number = %d' %global_number)

instance1 = threading.Thread(target=add1)
instance2 = threading.Thread(target=add2)
instance3 = threading.Thread(target=add3)

instance1.start()
instance2.start()
instance3.start()
print('---in main Thread g_num = %d---' %global_number)

全局变量传递参数


def append33(g_nums):
    g_nums.append(33)
    print("---g_num = %s" % str(g_nums))
def append22(g_nums):
    g_nums.append(22)
    print('--- g_num = %s---' % str(g_nums))
global_nums = [11, 22]

inst1 = threading.Thread(target=append33, args=(global_nums,))
inst2 = threading.Thread(target=append22, args=(global_nums,))

inst1.start()
inst2.start()

print('---in main Thread g_num = %s---' % str(global_nums))

在这里插入图片描述
资源竞争

g_num = 0
def a_cycle_add1(cycle_num):
    global g_num
    for i in range(cycle_num):
        g_num += 1
    print("--- g_num = %d" %g_num)
def b_cycle_add1(cycle_num):
    global g_num
    for i in range(cycle_num):
        g_num += 1
    print('--- g_num = %d---' %g_num)
instance1 = threading.Thread(target=a_cycle_add1,args=(1000000,))
instance2 = threading.Thread(target=b_cycle_add1,args=(1000000,))
instance1.start()
instance2.start()

print('---in main Thread g_num = %d---' %g_num)

在这里插入图片描述
全局解释器锁来说,就是在CPython上面才有的,它的原理是在解释器层面加上一把大锁,保证同一时刻只能有一个python线程在解释器中执行。
I/O密集型的python多线程进程,每个线程在等待I/O的时候,将会释放GIL资源,供别的线程来抢占。所以对于I/O密集型的python多线程进程来说,还是能比顺序执行的效率要高的。
互斥(mutex)锁:
当多个线程修改同一个数据的时候,如果操作的时间够短的话,能得到我们想要的结果,但是,如果修改数据不是原子性的(这中间的时间太长)的话。。。很有可能造成数据的错误覆盖,从而得到我们不想要的结果。

g_num = 0
def a_cycle_add1(cycle_num):
    global g_num

    for i in range(cycle_num):
        mutex.acquire()
        g_num += 1
        mutex.release()
    print(" in a g_num = %d" %g_num)
def b_cycle_add2(cycle_num):
    global g_num

    for i in range(cycle_num):
        mutex.acquire()
        g_num += 1
        mutex.release()
    print(' g_num = %d---' %g_num)
mutex = threading.Lock()
instance1 = threading.Thread(target=a_cycle_add1,args=(1000000,))
instance2 = threading.Thread(target=b_cycle_add2,args=(1000000,))

instance1.start()
instance2.start()

print('---in main Thread g_num = %d---' %g_num)

https://www.cnblogs.com/huxianglin/p/5973471.html
在这里插入图片描述

def recvfrom(udp_socket):
    while True:
        recv_data = udp_socket.recvfrom(1024)
        print(recv_data)
def sendto(udp_socket, dest_ip, dest_port):
    while True:
        send_data = input("请输入要发送的数据:")
        udp_socket.sendto(send_data.encode('utf-8'),(dest_ip,dest_port))

def main():
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp_socket.bind(('',7890))

    dest_ip = input('输入对方的ip:')
    dest_port = int(input(" 请输入对方的port: "))

    t_recv = threading.Thread(target=recvfrom,args=(udp_socket,))
    t_send = threading.Thread(target=sendto,args=(udp_socket, dest_ip, dest_port))
    t_recv.start()
    t_send.start()
if __name__ == "__main__":
    main()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值