1. 使用文件锁(File Lock)
文件锁是一种简单且常用的方法,用于防止多个进程同时访问共享资源。
(1)Bash 示例
在 Bash 脚本中,可以使用 flock
命令实现文件锁:
#!/bin/bash
# 定义锁文件
LOCKFILE="/var/lock/my_script.lock"
# 使用 flock 创建排他锁
(
flock -x 200
# 关键代码段
echo "脚本开始运行"
sleep 10 # 模拟耗时操作
echo "脚本结束运行"
) 200>"$LOCKFILE"
- 说明:
flock -x 200
表示获取一个排他锁。- 文件描述符
200
绑定到$LOCKFILE
,确保锁的作用范围。 - 当脚本退出时,锁会自动释放。
(2)Python 示例
在 Python 中,可以使用 fcntl
模块实现文件锁:
import fcntl
import time
# 定义锁文件
lock_file = open("/var/lock/my_script.lock", "w")
try:
# 获取排他锁
fcntl.flock(lock_file, fcntl.LOCK_EX)
print("脚本开始运行")
time.sleep(10) # 模拟耗时操作
print("脚本结束运行")
finally:
# 释放锁
fcntl.flock(lock_file, fcntl.LOCK_UN)
lock_file.close()
2. 使用信号量(Semaphore)
信号量是一种更高级的同步机制,适用于复杂的并发场景。
(1)Python 示例
在 Python 中,可以使用 threading.Semaphore
或 multiprocessing.Semaphore
实现信号量:
import threading
import time
# 定义信号量
semaphore = threading.Semaphore(1)
def critical_section():
semaphore.acquire()
try:
print("进入关键代码段")
time.sleep(5) # 模拟耗时操作
print("退出关键代码段")
finally:
semaphore.release()
# 模拟并发执行
threads = [threading.Thread(target=critical_section) for _ in range(5)]
for t in threads:
t.start()
for t in threads:
t.join()
3. 使用数据库事务
如果共享资源存储在数据库中,可以通过数据库事务来避免竞争条件。
(1)SQL 示例
假设您使用的是 MySQL 数据库,可以通过事务确保操作的原子性:
START TRANSACTION;
-- 更新共享资源
UPDATE resource_table SET value = value + 1 WHERE id = 1;
COMMIT;
(2)Python 示例
结合 SQLAlchemy
使用事务:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# 创建数据库连接
engine = create_engine("mysql+pymysql://user:password@host/dbname")
Session = sessionmaker(bind=engine)
session = Session()
try:
# 开始事务
session.begin()
# 更新共享资源
resource = session.execute("SELECT * FROM resource_table WHERE id = 1 FOR UPDATE").fetchone()
session.execute("UPDATE resource_table SET value = value + 1 WHERE id = 1")
# 提交事务
session.commit()
except Exception as e:
# 回滚事务
session.rollback()
print(f"发生错误: {e}")
finally:
session.close()
4. 限制并发执行
如果不需要完全并行执行,可以通过限制并发数来避免竞争条件。
(1)Bash 示例
使用 pgrep
和 wc -l
检查当前运行的脚本实例数:
#!/bin/bash
# 最大并发数
MAX_CONCURRENT=1
# 检查当前运行的实例数
current_running=$(pgrep -fc "$(basename $0)" || true)
if [ "$current_running" -ge "$MAX_CONCURRENT" ]; then
echo "已有 $current_running 个实例运行,退出"
exit 1
fi
# 脚本逻辑
echo "脚本开始运行"
sleep 10 # 模拟耗时操作
echo "脚本结束运行"
(2)Python 示例
使用 concurrent.futures
限制并发数:
from concurrent.futures import ThreadPoolExecutor
import time
def task():
print("任务开始")
time.sleep(5) # 模拟耗时操作
print("任务结束")
# 最大并发数
MAX_WORKERS = 2
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
futures = [executor.submit(task) for _ in range(5)]
for future in futures:
future.result()
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容