Skip to content

Commit 71d0498

Browse files
committed
单例加锁
单例加锁
1 parent e826812 commit 71d0498

1 file changed

Lines changed: 66 additions & 2 deletions

File tree

python_basic/new和init方法.md

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,78 @@
66
## \_\_new__()实现单例
77
```python
88
class Singleton:
9+
910
def __new__(cls, *args, **kwargs):
1011
if not hasattr(cls, 'instance'):
1112
cls.instance = super().__new__(cls)
1213
return cls.instance
1314

14-
1515
if __name__ == '__main__':
1616
s1 = Singleton()
1717
s2 = Singleton()
18-
print(s1 is s2) # True
18+
print('s1:{}'.format(id(s1)))
19+
print('s2:{}'.format(id(s2)))
20+
print('s1 is s2:{}'.format(s1 is s2))
21+
```
22+
```python
23+
s1:1891632871352
24+
s2:1891632871352
25+
s1 is s2:True
26+
```
27+
28+
**以上看似实现了单例模式,但实际在多线程的情况下会有问题,多个线程同时创建单例对象,如果不加锁的情况下是不安全的。**
29+
30+
```python
31+
import time
32+
import threading
33+
34+
class Singleton:
35+
36+
def __new__(cls, *args, **kwargs):
37+
if not hasattr(cls, 'instance'):
38+
time.sleep(0.05)
39+
cls.instance = super().__new__(cls)
40+
return cls.instance
41+
42+
def func():
43+
s = Singleton()
44+
print('s:{}'.format(id(s)))
45+
46+
if __name__ == '__main__':
47+
for _ in range(5):
48+
# 开启5个线程同时创建对象
49+
td = threading.Thread(target=func)
50+
td.start()
51+
```
52+
```python
53+
s:1230297165896
54+
s:1230297245008
55+
s:1230297372152
56+
s:1230297270648
57+
s:1230297296176
58+
```
59+
60+
**多线程先创建单例对象需要加锁**
61+
62+
```python
63+
import threading
64+
65+
class Singleton:
66+
_instance_lock = threading.Lock()
67+
68+
def __new__(cls, *args, **kwargs):
69+
# 加锁
70+
with cls._instance_lock:
71+
if not hasattr(cls, 'instance'):
72+
cls.instance = super().__new__(cls)
73+
return cls.instance
74+
75+
def func():
76+
s = Singleton()
77+
print('s:{}'.format(id(s)))
78+
79+
if __name__ == '__main__':
80+
for _ in range(5):
81+
td = threading.Thread(target=func)
82+
td.start()
1983
```

0 commit comments

Comments
 (0)