多线程环境更新TOKEN优化记录_240907

多线程环境下,为确保资源的合理利用和数据一致性,通常需要用到同步控制。在处理如更新TOKEN这类涉及共享资源操作时,防止多个线程同时进行更新操作是关键。以下将具体探讨如何实现这一目标:

1. **使用锁机制**
   - **简单锁**:最简单的方法是使用一个普通锁或 `synchronized`代码块来同步访问更新函数的代码段。当一个线程进入同步代码块进行TOKEN更新时,其他线程将会等待直到第一个线程完成更新并释放锁。
   - **双重检查锁定**:这是一种常用的单例模式中的技术,可以用来减少锁的使用频率,只在首次初始化时进行同步。这在某些情况下可以优化性能,但在更新TOKEN的场景中可能不适用,因为每次更新都需要重新获取锁。
2. **使用信号量**
   - **Semaphore**: 信号量通过计数来控制对共享资源的访问。可以设置一个计数为1的信号量,这样每次只有一个线程能获得信号量并执行更新操作。其他线程将不得不等待信号量释放。
3. **使用原子操作**
   - **AtomicBoolean**: 使用原子操作可以保证操作的原子性,无锁地实现同步。例如,可以使用 `AtomicBoolean`来标记更新操作的状态,判断是否需要进行更新。

4. **使用阻塞队列**
   - **BlockingQueue**: 创建一个单元素的阻塞队列。任何需要更新TOKEN的线程都尝试向队列插入元素。如果队列已满,线程将等待直到有空间可用。这样就能确保同时只有一个线程进行更新操作。
5. **使用读写锁**
   - **ReentrantReadWriteLock**: 如果除了更新TOKEN外,还有读取TOKEN的操作,并且希望在读取时不互相阻塞,那么使用读写锁是更好的选择。这样可以允许多个读操作并行,而写操作(更新TOKEN)仍然是互斥的。
6. **使用线程池和任务队列**
   - **ExecutorService**: 创建一个单线程的线程池。所有需要更新TOKEN的任务都提交给这个线程池。由于线程池只有一个线程,因此这些任务将会排队按顺序执行,从而避免了并发更新的问题。
   - **Future和Callable**: 结合使用 `Future`和 `Callable`可以更加灵活地控制并发任务的执行和结果获取。可以在Callable任务中编写更新逻辑,通过 `Future.get()`等待任务完成并获取结果。


class AtomicBoolean:
    def __init__(self, value=False):
        self._value = value  # 初始化原子布尔值,默认为False
        self._lock = threading.Lock()  # 创建一个锁对象,用于同步访问

    def set(self, new_value):
        with self._lock:  # 使用锁来确保原子操作
            self._value = new_value  # 设置新的布尔值

    def get(self):
        with self._lock:  # 使用锁来确保原子操作
            return self._value  # 返回当前的布尔值

    def compare_and_set(self, expected_value, new_value):
        with self._lock:  # 使用锁来确保原子操作
            if self._value == expected_value:  # 如果当前值等于期望值
                self._value = new_value  # 更新值为新值
                return True  # 返回True表示更新成功
            return False  # 返回False表示更新失败

 

    atomic_flag = AtomicBoolean()  # 创建一个AtomicBoolean实例
    # 假设您已经有一个名为result_list的ICCID列表
    with concurrent.futures.ThreadPoolExecutor(max_workers=100) as executor:
        # 提交任务给线程池
        futures = [executor.submit(process_iccid, i, iccid, atomic_flag,运营商) for i, (iccid,运营商) in enumerate(results)]
        # 处理每个任务的结果
        temp_updates = []
        for i,future in enumerate(concurrent.futures.as_completed(futures)):
            try:
                result = future.result()
                # print(f"{i}-{result[1]}")
                # 处理任务结果的逻辑
                # i, iccid,update_statement,values
                temp_updates.append((f'{result[0]}_剩余{len(results)}_共计{len1}',f'{result[1]}', f'{result[2]}', f'{result[3]}'))
                # print(f"序列号:{result[0]}-ICCID:{result[1]}")

                # 当temp_updates达到一定数量时,执行batch_update函数
                if len(temp_updates) == 100:
                    # print(f"开始执行:{len(temp_updates)}")
                    # logger.info(f"temp_updates:{len(temp_updates)}")
                    batch_update(temp_updates, DB_SQLITE, table_name)
                    temp_updates = []
                    # print(f"执行结束:{len(temp_updates)}")
            except Exception as e:
                # 处理任务执行过程中的异常
                print(f"任务执行出现异常: {e}")
                # logger.error(f"任务执行出现异常: {e}")
                continue
        # 如果还有剩余的任务结果,执行batch_update函数
        if temp_updates:
            batch_update(temp_updates, DB_SQLITE, table_name)

def process_iccid(i, iccid, atomic_flag,运营商):
    #
    #
    elif (status[0] == '12021'):  # TOKEN不存在或已过期,请重新获取
            logger.debug(f"{运营商}:TOKEN已过期,请重新获取")
            if atomic_flag.compare_and_set(False, True):  # 尝试将原子布尔值从False更新为True
                token_reset()
                atomic_flag.set(False)  # 更新完成后将原子布尔值重置为False
                logger.debug(f"{运营商}:TOKEN更新已完成")
            else:
                logger.debug("其他线程正在更新,跳过本次更新")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值