gpt4 book ai didi

java - 通过键名锁定数据库编辑

转载 作者:行者123 更新时间:2023-12-02 00:51:29 26 4
gpt4 key购买 nike

我需要防止同时编辑数据库字段。用户正在对结构化数据字段执行推送操作,因此我想对操作进行排序,而不是简单地忽略一次编辑并进行第二次编辑。

基本上我想做

synchronized(key name)
{
push value onto the database field
}

并设置同步项,以便一次仅对“键名”进行一项操作。 (注意:我正在简化,这并不总是简单的插入)。

实现此目的的一种粗略方法是全局同步,但这会成为整个应用程序的瓶颈。我需要做的就是使用相同的 key 对两个同时写入进行排序,这种情况很少见,但很烦人。

这是一个基于 Web 的 Java 应用程序,用 Spring 编写(并使用 JPA/MySQL)。该操作由用户 Web 服务调用触发。 (根本原因是用户使用相同的 key 同时发送两个 http 请求)。

我浏览了 Doug Lea/Josh Bloch/et al Concurrency in Action,但没有看到明显的解决方案。不过,这看起来很简单,我觉得必须有一种优雅的方法来做到这一点。

最佳答案

可能有一种简单的方法可以让您的数据库为您处理这个问题。诚然,我在数据库方面的知识很薄弱。取而代之的是,这里有一种方法,涉及为每个键名创建一个单独的锁。有一个存储库管理单个锁的创建/销毁,这些锁需要一个适用于整个应用程序的锁,但它仅在找到、创建或销毁单个键名锁时保留该锁。为实际数据库操作持有的锁是该操作中使用的键名称所独有的。

KeyLock 类用于防止对单个键名同时进行数据库操作。

package KeyLocks;

import java.util.concurrent.locks.Lock;

public class KeyLock
{
private final KeyLockManager keyLockManager;
private final String keyName;
private final Lock lock;

KeyLock(KeyLockManager keyLockManager, String keyName, Lock lock)
{
this.keyLockManager = keyLockManager;
this.keyName = keyName;
this.lock = lock;
}

@Override
protected void finalize()
{
release();
}

public void release()
{
keyLockManager.releaseLock(keyName);
}

public void lock()
{
lock.lock();
}

public void unlock()
{
lock.unlock();
}
}

KeyLockManager 类是负责 key 锁生命周期的存储库。

package KeyLocks;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class KeyLockManager
{
private class LockEntry
{
int acquisitionCount = 0;
final Lock lock = new ReentrantLock();
}

private final Map<String, LockEntry> locks = new HashMap<String, LockEntry>();
private final Object mutex = new Object();

public KeyLock getLock(String keyName)
{
synchronized (mutex)
{
LockEntry lockEntry = locks.get(keyName);
if (lockEntry == null)
{
lockEntry = new LockEntry();
locks.put(keyName, lockEntry);
}
lockEntry.acquisitionCount++;
return new KeyLock(this, keyName, lockEntry.lock);
}
}

void releaseLock(String keyName)
{
synchronized (mutex)
{
LockEntry lockEntry = locks.get(keyName);
lockEntry.acquisitionCount--;
if (lockEntry.acquisitionCount == 0)
{
locks.remove(keyName);
}
}
}
}

以下是如何使用 key 锁的示例。

package test;

import KeyLocks.KeyLock;
import KeyLocks.KeyLockManager;

public class Main
{
private static final String KEY_NAME = "TEST_KEY";

public static void main(String[] args)
{
final KeyLockManager keyLockManager = new KeyLockManager();
KeyLock keyLock = null;
try
{
keyLock = keyLockManager.getLock(KEY_NAME);
keyLock.lock();
try
{
// Do database operation on the data with the specified key name
}
finally
{
keyLock.unlock();
}
}
finally
{
if (keyLock != null)
{
keyLock.release();
}
}
}
}

关于java - 通过键名锁定数据库编辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2844744/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com