当前位置:首页 » 编程语言 » python变量锁

python变量锁

发布时间: 2023-02-27 07:04:13

1. python多线程全局变量和锁

1.python中数据类型,int,float,复数,字符,元组,做全局变量时需要在函数里面用global申明变量,才能对变量进行操作。

而,对象,列表,词典,不需要声明,直接就是全局的。

2.线程锁mutex=threading.Lock()

创建后就是全局的。线程调用函数可以直接在函数中使用。

mutex.acquire()开启锁

mutex=release()关闭锁

要注意,死锁的情况发生。

注意运行效率的变化:

正常1秒,完成56997921

加锁之后,1秒只运行了531187,相差10倍多。

3.继承.threading.Thread的类,无法调用__init__函数,无法在创建对象时初始化新建的属性。

4.线程在cpu的执行,有随机性

5. 新建线程时,需要传参数时,args是一个元组,如果只有一个参数,一定后面要加一个,符号。不能只有一个参数否则线程会报创建参数错误。threading.Thread(target=fuc,args=(arg,))

2. python多个线程锁可提高效率吗

首先,Python的多线程本身就是效率极低的,因为有GIL(Global Interpreter Lock:全局解释锁)机制的限制,其作用简单说就是:对于一个解释器,只能有一个线程在执行bytecode。
所以如果为了追求传统意义上多线程的效率,在Python界还是用多进程(multiprocessing)吧……
这里你用了多线程,且用了锁来控制公共资源,首先锁这个东西会导致死锁,不加锁反而没有死锁隐患,但会有同步问题。
另外,如果不同线程操作的是不同的文件,是不存在同步问题的,如果操作同一个文件,我建议采用Queue(队列)来处理。
总的来说,用单线程就好了,因为Python多线程本身就没什么效率,而且单线程也不用考虑同步问题了。非要追求效率的话,就用多进程吧,同样也要考虑进程锁。

3. Python为什么要有全局锁

多进程和多线程 需要锁,不然会造成输出结果错乱。比如:同时print("hello world!"),会造成这样的结果:hehello worldllo world,会同时打印在一起。锁是避免出现这种情况。

4. Python中的各种锁

大致罗列一下:
一、全局解释器锁(GIL)
1、什么是全局解释器锁
每个CPU在同一时间只能执行一个线程,那么其他的线程就必须等待该线程的全局解释器,使用权消失后才能使用全局解释器,即使多个线程直接不会相互影响在同一个进程下也只有一个线程使用cpu,这样的机制称为全局解释器锁(GIL)。GIL的设计简化了CPython的实现,使的对象模型包括关键的内建类型,如:字典等,都是隐含的,可以并发访问的,锁住全局解释器使得比较容易的实现对多线程的支持,但也损失了多处理器主机的并行计算能力。
2、全局解释器锁的好处
1)、避免了大量的加锁解锁的好处
2)、使数据更加安全,解决多线程间的数据完整性和状态同步
3、全局解释器的缺点
多核处理器退化成单核处理器,只能并发不能并行。
4、GIL的作用:
多线程情况下必须存在资源的竞争,GIL是为了保证在解释器级别的线程唯一使用共享资源(cpu)。
二、同步锁
1、什么是同步锁?
同一时刻的一个进程下的一个线程只能使用一个cpu,要确保这个线程下的程序在一段时间内被cpu执,那么就要用到同步锁。
2、为什么用同步锁?
因为有可能当一个线程在使用cpu时,该线程下的程序可能会遇到io操作,那么cpu就会切到别的线程上去,这样就有可能会影响到该程序结果的完整性。
3、怎么使用同步锁?
只需要在对公共数据的操作前后加上上锁和释放锁的操作即可。
4、同步锁的所用:
为了保证解释器级别下的自己编写的程序唯一使用共享资源产生了同步锁。
三、死锁
1、什么是死锁?
指两个或两个以上的线程或进程在执行程序的过程中,因争夺资源或者程序推进顺序不当而相互等待的一个现象。
2、死锁产生的必要条件?
互斥条件、请求和保持条件、不剥夺条件、环路等待条件
3、处理死锁的基本方法?
预防死锁、避免死锁(银行家算法)、检测死锁(资源分配)、解除死锁:剥夺资源、撤销进程
四、递归锁
在Python中为了支持同一个线程中多次请求同一资源,Python提供了可重入锁。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。递归锁分为可递归锁与非递归锁。
五、乐观锁
假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。
六、悲观锁
假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
python常用的加锁方式:互斥锁、可重入锁、迭代死锁、互相调用死锁、自旋锁。

5. python有哪些特点和优点

显着的优点

Python 语言拥有诸多的优点,这其中,以下几个优点特别显着:

简单易学:Python语言相对于其他编程语言来说,属于比较容易学习的一门编程语言,它注重的是如何解决问题而不是编程语言的语法和结构。正是因为Python语言简单易学,所以,已经有越来越多的初学者选择Python语言作为编程的入门语言。例如,在浙江省 2017年高中信息技术改革中,《算法与程序设计》课程将使用 Python语言替换原有的VB 语言。

语法优美:Python语言力求代码简洁、优美。在Python语言中,采用缩进来标识代码块,通过减少无用的大括号,去除语句末尾的分号等视觉杂讯,使得代码的可读性显着提高。阅读一段良好的Python程序就感觉像是在读英语一样,它使你能够专注于解决问题,而不用太纠结编程语言本身的语法。

丰富强大的库:Python语言号称自带电池(Battery Included),寓意是Python语言的类库非常的全面,包含了解决各种问题的类库。无论实现什么功能,都有现成的类库可以使用。如果一个功能比较特殊,标准库没有提供相应的支持,那么,很大概率也会有相应的开源项目提供了类似的功能。合理使用Python的类库和开源项目,能够快速的实现功能,满足业务需求。

开发效率高:Python的各个优点是相辅相成的。例如,Python语言因为有了丰富强大的类库,所以,Python的开发效率能够显着提高。相对于 C、C++ 和 Java等编译语言,Python开发者的效率提高了数倍。实现相同的功能,Python代码的文件往往只有 C、C++和Java代码的1/5~1/3。虽然Python语言拥有很多吸引人的特性,但是,各大互联网公司广泛使用Python语言,很大程度上是因为Python语言开发效率高这个特点。开发效率高的语言,能够更好的满足互联网快速迭代的需求,因此,Python语言在互联网公司使用非常广泛。

应用领域广泛:Python语言的另一大优点就是应用领域广泛,工程师可以使用Python 做很多的事情。例如,Web开发、网络编程、自动化运维、Linux系统管理、数据分析、科学计算、人工智能、机器学习等等。Python语言介于脚本语言和系统语言之间,我们根据需要,既可以将它当做一门脚本语言来编写脚本,也可以将它当做一个系统语言来编写服务。

不可忽视的缺点

毫无疑问,Python确实有用很多的优点,每一个优点看起来都非常吸引人。但是,Python并不是没有缺点的,最主要的缺点有以下几个:

Python的执行速度不够快。当然,这也不是一个很严重的问题,一般情况下,我们不会拿Python语言与C/C++这样的语言进行直接比较。在Python语言的执行速度上,一方面,网络或磁盘的延迟,会抵消掉部分Python本身消耗的时间;另一方面,因为Python 特别容易和C结合起来,因此,我们可以通过分离一部分需要优化速度的应用,将其转换为编译好的扩展,并在整个系统中使用Python脚本将这部分应用连接起来,以提高程序的整体效率。

Python的GIL锁限制并发:Python的另一个大问题是,对多处理器支持不好。如果读者接触Python时间比较长,那么,一定听说过GIL这个词。GIL是指Python全局解释器锁(Global Interpreter Lock),当Python的默认解释器要执行字节码时,都需要先申请这个锁。这意味着,如果试图通过多线程扩展应用程序,将总是被这个全局解释器锁限制。当然,我们可以使用多进程的架构来提高程序的并发,也可以选择不同的Python实现来运行我们的程序。

Python 2与Python 3不兼容: 如果一个普通的软件或者库,不能够做到后向兼容,那么,它会被用户无情的抛弃了。在Python中,一个槽点是Python 2与Python 3不兼容。因为Python没有向后兼容,给所有的Python工程师带来了无数的烦恼。

上述就是总结的Python语言的优缺点。总体来说,Python目前的发展还是非常不错的。借着人工智能时代的东风,Python开发人员的未来一定会很光明。

6. 深入解析Python中的线程同步方法

深入解析Python中的线程同步方法
同步访问共享资源
在使用线程的时候,一个很重要的问题是要避免多个线程对同一变量或其它资源的访问冲突。一旦你稍不留神,重叠访问、在多个线程中修改(共享资源)等这些操作会导致各种各样的问题;更严重的是,这些问题一般只会在比较极端(比如高并发、生产服务器、甚至在性能更好的硬件设备上)的情况下才会出现。
比如有这样一个情况:需要追踪对一事件处理的次数
counter = 0

def process_item(item):
global counter
... do something with item ...
counter += 1
如果你在多个线程中同时调用这个函数,你会发现counter的值不是那么准确。在大多数情况下它是对的,但有时它会比实际的少几个。
出现这种情况的原因是,计数增加操作实际上分三步执行:
解释器获取counter的当前值计算新值将计算的新值回写counter变量
考虑一下这种情况:在当前线程获取到counter值后,另一个线程抢占到了CPU,然后同样也获取到了counter值,并进一步将counter值重新计算并完成回写;之后时间片重新轮到当前线程(这里仅作标识区分,并非实际当前),此时当前线程获取到counter值还是原来的,完成后续两步操作后counter的值实际只加上1。
另一种常见情况是访问不完整或不一致状态。这类情况主要发生在一个线程正在初始化或更新数据时,另一个进程却尝试读取正在更改的数据。
原子操作
实现对共享变量或其它资源的同步访问最简单的方法是依靠解释器的原子操作。原子操作是在一步完成执行的操作,在这一步中其它线程无法获得该共享资源。
通常情况下,这种同步方法只对那些只由单个核心数据类型组成的共享资源有效,譬如,字符串变量、数字、列表或者字典等。下面是几个线程安全的操作:
读或者替换一个实例属性读或者替换一个全局变量从列表中获取一项元素原位修改一个列表(例如:使用append增加一个列表项)从字典中获取一项元素原位修改一个字典(例如:增加一个字典项、调用clear方法)
注意,上面提到过,对一个变量或者属性进行读操作,然后修改它,最终将其回写不是线程安全的。因为另外一个线程会在这个线程读完却没有修改或回写完成之前更改这个共享变量/属性。

锁是Python的threading模块提供的最基本的同步机制。在任一时刻,一个锁对象可能被一个线程获取,或者不被任何线程获取。如果一个线程尝试去获取一个已经被另一个线程获取到的锁对象,那么这个想要获取锁对象的线程只能暂时终止执行直到锁对象被另一个线程释放掉。
锁通常被用来实现对共享资源的同步访问。为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问完后,再调用release方法释放锁:
lock = Lock()

lock.acquire() #: will block if lock is already held
... access shared resource
lock.release()

注意,即使在访问共享资源的过程中出错了也应该释放锁,可以用try-finally来达到这一目的:
lock.acquire()
try:
... access shared resource
finally:
lock.release() #: release lock, no matter what

在Python 2.5及以后的版本中,你可以使用with语句。在使用锁的时候,with语句会在进入语句块之前自动的获取到该锁对象,然后在语句块执行完成后自动释放掉锁:
from __future__ import with_statement #: 2.5 only

with lock:
... access shared resource

acquire方法带一个可选的等待标识,它可用于设定当有其它线程占有锁时是否阻塞。如果你将其值设为False,那么acquire方法将不再阻塞,只是如果该锁被占有时它会返回False:
if not lock.acquire(False):
... 锁资源失败
else:
try:
... access shared resource
finally:
lock.release()

你可以使用locked方法来检查一个锁对象是否已被获取,注意不能用该方法来判断调用acquire方法时是否会阻塞,因为在locked方法调用完成到下一条语句(比如acquire)执行之间该锁有可能被其它线程占有。
if not lock.locked():
#: 其它线程可能在下一条语句执行之前占有了该锁
lock.acquire() #: 可能会阻塞

简单锁的缺点
标准的锁对象并不关心当前是哪个线程占有了该锁;如果该锁已经被占有了,那么任何其它尝试获取该锁的线程都会被阻塞,即使是占有锁的这个线程。考虑一下下面这个例子:
lock = threading.Lock()

def get_first_part():
lock.acquire()
try:
... 从共享对象中获取第一部分数据
finally:
lock.release()
return data

def get_second_part():
lock.acquire()
try:
... 从共享对象中获取第二部分数据
finally:
lock.release()
return data

示例中,我们有一个共享资源,有两个分别取这个共享资源第一部分和第二部分的函数。两个访问函数都使用了锁来确保在获取数据时没有其它线程修改对应的共享数据。
现在,如果我们想添加第三个函数来获取两个部分的数据,我们将会陷入泥潭。一个简单的方法是依次调用这两个函数,然后返回结合的结果:

def get_both_parts():
first = get_first_part()
seconde = get_second_part()
return first, second

这里的问题是,如有某个线程在两个函数调用之间修改了共享资源,那么我们最终会得到不一致的数据。最明显的解决方法是在这个函数中也使用lock:
def get_both_parts():
lock.acquire()
try:
first = get_first_part()
seconde = get_second_part()
finally:
lock.release()
return first, second

然而,这是不可行的。里面的两个访问函数将会阻塞,因为外层语句已经占有了该锁。为了解决这个问题,你可以通过使用标记在访问函数中让外层语句释放锁,但这样容易失去控制并导致出错。幸运的是,threading模块包含了一个更加实用的锁实现:re-entrant锁。
Re-Entrant Locks (RLock)

RLock类是简单锁的另一个版本,它的特点在于,同一个锁对象只有在被其它的线程占有时尝试获取才会发生阻塞;而简单锁在同一个线程中同时只能被占有一次。如果当前线程已经占有了某个RLock锁对象,那么当前线程仍能再次获取到该RLock锁对象。
lock = threading.Lock()
lock.acquire()
lock.acquire() #: 这里将会阻塞

lock = threading.RLock()
lock.acquire()
lock.acquire() #: 这里不会发生阻塞

RLock的主要作用是解决嵌套访问共享资源的问题,就像前面描述的示例。要想解决前面示例中的问题,我们只需要将Lock换为RLock对象,这样嵌套调用也会OK.
lock = threading.RLock()

def get_first_part():
... see above

def get_second_part():
... see above

def get_both_parts():
... see above

这样既可以单独访问两部分数据也可以一次访问两部分数据而不会被锁阻塞或者获得不一致的数据。
注意RLock会追踪递归层级,因此记得在acquire后进行release操作。
Semaphores

信号量是一个更高级的锁机制。信号量内部有一个计数器而不像锁对象内部有锁标识,而且只有当占用信号量的线程数超过信号量时线程才阻塞。这允许了多个线程可以同时访问相同的代码区。
semaphore = threading.BoundedSemaphore()
semaphore.acquire() #: counter减小

... 访问共享资源
semaphore.release() #: counter增大

当信号量被获取的时候,计数器减小;当信号量被释放的时候,计数器增大。当获取信号量的时候,如果计数器值为0,则该进程将阻塞。当某一信号量被释放,counter值增加为1时,被阻塞的线程(如果有的话)中会有一个得以继续运行。
信号量通常被用来限制对容量有限的资源的访问,比如一个网络连接或者数据库服务器。在这类场景中,只需要将计数器初始化为最大值,信号量的实现将为你完成剩下的事情。
max_connections = 10

semaphore = threading.BoundedSemaphore(max_connections)

如果你不传任何初始化参数,计数器的值会被初始化为1.
Python的threading模块提供了两种信号量实现。Semaphore类提供了一个无限大小的信号量,你可以调用release任意次来增大计数器的值。为了避免错误出现,最好使用BoundedSemaphore类,这样当你调用release的次数大于acquire次数时程序会出错提醒。
线程同步

锁可以用在线程间的同步上。threading模块包含了一些用于线程间同步的类。
Events

一个事件是一个简单的同步对象,事件表示为一个内部标识(internal flag),线程等待这个标识被其它线程设定,或者自己设定、清除这个标识。
event = threading.Event()

#: 一个客户端线程等待flag被设定
event.wait()

#: 服务端线程设置或者清除flag
event.set()
event.clear()

一旦标识被设定,wait方法就不做任何处理(不会阻塞),当标识被清除时,wait将被阻塞直至其被重新设定。任意数量的线程可能会等待同一个事件。
Conditions

条件是事件对象的高级版本。条件表现为程序中的某种状态改变,线程可以等待给定条件或者条件发生的信号。
下面是一个简单的生产者/消费者实例。首先你需要创建一个条件对象:

#: 表示一个资源的附属项
condition = threading.Condition()
生产者线程在通知消费者线程有新生成资源之前需要获得条件:
#: 生产者线程
... 生产资源项
condition.acquire()
... 将资源项添加到资源中
condition.notify() #: 发出有可用资源的信号
condition.release()
消费者必须获取条件(以及相关联的锁),然后尝试从资源中获取资源项:
#: 消费者线程
condition.acquire()
while True:
...从资源中获取资源项
if item:
break
condition.wait() #: 休眠,直至有新的资源
condition.release()
... 处理资源

wait方法释放了锁,然后将当前线程阻塞,直到有其它线程调用了同一条件对象的notify或者notifyAll方法,然后又重新拿到锁。如果同时有多个线程在等待,那么notify方法只会唤醒其中的一个线程,而notifyAll则会唤醒全部线程。
为了避免在wait方法处阻塞,你可以传入一个超时参数,一个以秒为单位的浮点数。如果设置了超时参数,wait将会在指定时间返回,即使notify没被调用。一旦使用了超时,你必须检查资源来确定发生了什么。
注意,条件对象关联着一个锁,你必须在访问条件之前获取这个锁;同样的,你必须在完成对条件的访问时释放这个锁。在生产代码中,你应该使用try-finally或者with.
可以通过将锁对象作为条件构造函数的参数来让条件关联一个已经存在的锁,这可以实现多个条件公用一个资源:
lock = threading.RLock()
condition_1 = threading.Condition(lock)
condition_2 = threading.Condition(lock)

互斥锁同步
我们先来看一个例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, threading

# 假定这是你的银行存款:
balance = 0
muxlock = threading.Lock()

def change_it(n):
# 先存后取,结果应该为0:
global balance
balance = balance + n
balance = balance - n

def run_thread(n):
# 循环次数一旦多起来,最后的数字就变成非0
for i in range(100000):
change_it(n)

t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t3 = threading.Thread(target=run_thread, args=(9,))
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print balance

结果 :

[/data/web/test_python]$ python multhread_threading.py
0
[/data/web/test_python]$ python multhread_threading.py
61
[/data/web/test_python]$ python multhread_threading.py
0
[/data/web/test_python]$ python multhread_threading.py
24

上面的例子引出了多线程编程的最常见问题:数据共享。当多个线程都修改某一个共享数据的时候,需要进行同步控制。
线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

threading模块中定义了Lock类,可以方便的处理锁定:
#创建锁mutex = threading.Lock()
#锁定mutex.acquire([timeout])
#释放mutex.release()

其中,锁定方法acquire可以有一个超时时间的可选参数timeout。如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁,从而可以进行一些其他的处理。
使用互斥锁实现上面的例子的代码如下:
balance = 0
muxlock = threading.Lock()

def change_it(n):
# 获取锁,确保只有一个线程操作这个数
muxlock.acquire()
global balance
balance = balance + n
balance = balance - n
# 释放锁,给其他被阻塞的线程继续操作
muxlock.release()

def run_thread(n):
for i in range(10000):
change_it(n)

加锁后的结果,就能确保数据正确:
[/data/web/test_python]$ python multhread_threading.py
0
[/data/web/test_python]$ python multhread_threading.py
0
[/data/web/test_python]$ python multhread_threading.py
0
[/data/web/test_python]$ python multhread_threading.py
0

7. Python多线程之threading之Lock对象

要介绍Python的 threading 模块中的 Lock 对象前, 首先应该了解以下两个概念:

1.基本概念 : 指某个函数/函数库在多线程环境中被调用时, 能够正确地处理多个线程之间的 共享变量 , 使程序功能正常完成. 多个线程访问同一个对象时, 如果不用考虑这些线程在运行时环境下的调度和交替执行, 也不需要进行额外的同步, 或者在调用方进行任何其他操作,调用这个对象的行为都可以获得正确的结果, 那么这个对象就是线程安全的. 或者说: 一个类或者程序所提供的接口对于线程来说是 原子操作 或者多个线程之间的切换不会导致该接口的执行结果存在二义性, 也就是说我们不用考虑同步的问题.

2.示例 : 比如有间银行只有1000元, 而两个人同时提领1000元时,就有可能拿到总计2000元的金额. 为了避免这个问题, 该间银行提款时应该使用 互斥锁 , 即意味着对同一个资源处理时, 前一个提领交易完成后才处理下一笔交易.

3.线程安全意义 :

4.是否线程安全 :

5.资源竞争 : 即多个线程对同一个资源的改写时, 存在的一种竞争. 如果仅仅是读操作, 则不存在资源竞争的情况.

1.基本概念 : 因为存在上述所说的 线程安全与资源竞争 的情况, 所以引入了 线程锁 . 即通过锁来进行资源请求的限制, 以保证同步执行,避免资源被污染或预期结果不符. 线程锁存在两种状态: 锁定(locked)和非锁定(unlocked).

2.基本方法 :

3.使用示例 :

上述示例如果在不加锁的情况下, 将会出现打印顺序混乱的情况, 不过最终结果都是正确的, 因为即使线程交替执行, 但最终的结果都是一致.

8. 怎么样给python文件加密

简单模式:
from hashlib import md5
def md5_file(name):
m = md5()
a_file = open(name, 'rb') #需要使用二进制格式读取文件内容
m.update(a_file.read())
a_file.close()
return m.hexdigest()
if __main__ == '__init__':
print md5_file('d:/test.txt')
大文件速度更快一点的方式
#!/usr/bin/python
#encoding=utf-8
import io
import sys
import hashlib
import string
def printUsage():
print ('''''Usage: [python] pymd5sum.py ''')
def main():
if(sys.argv.__len__()==2):
#print(sys.argv[1])
m = hashlib.md5()
file = io.FileIO(sys.argv[1],'r')
bytes = file.read(1024)
while(bytes != b''):
m.update(bytes)
bytes = file.read(1024)
file.close()
#md5value = ""
md5value = m.hexdigest()
print(md5value+"\t"+sys.argv[1])
#dest = io.FileIO(sys.argv[1]+".CHECKSUM.md5",'w')
#dest.write(md5value)
#dest.close()
else:
printUsage()
main()

热点内容
致炫x自豪版有哪些配置 发布:2024-05-16 17:04:12 浏览:670
关掉密码要往哪里关 发布:2024-05-16 16:46:03 浏览:370
网站源码查杀 发布:2024-05-16 16:02:53 浏览:834
服务器不用导轨怎么办 发布:2024-05-16 15:49:09 浏览:180
如何查看pppoe密码 发布:2024-05-16 15:38:02 浏览:174
云服务器成本价大概多少 发布:2024-05-16 15:33:42 浏览:446
正式服海岛冰茶怎么配置 发布:2024-05-16 15:25:39 浏览:290
安卓怎么注销探探 发布:2024-05-16 15:24:38 浏览:960
ata72x是多大的压缩机 发布:2024-05-16 15:07:59 浏览:95
安卓如何实现carplay的功能 发布:2024-05-16 15:02:54 浏览:713