微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在java中请求锁定数据结构的数据

如何解决如何在java中请求锁定数据结构的数据

最近,在研究现代数据库中的事务时,我发现如今的事务不会在整个集合或表上使用锁或监视器,但它们通常会在将要使用的集合或表的数据上使用锁或监视器由事务执行的不同操作使用。

所以我在想,假设我们有一个数据结构,它可以是 LinkedList、Hashtable 等,并且多个不同的事务想要同时访问该结构以更新数据。我如何要求锁定事务将使用的数据而不是整个对象数据结构?这显然会提高性能,因为使用相同数据结构的不同数据的不同更新事务会并发发生。

我会尽量澄清我想要实现的目标,这是一个例子:

public class Table {

    // suppose this is the data of the table and it has a lot of values
    private LinkedList<String> data = new LinkedList();

    public void doTransactionJob() {

        // here we get the data from the list
        // and we ask for monitor on this data so that no other
        // transaction can operate on it
        synchronized(data.get(randomIndex)) {
            // here the transaction works on the data but doesnt
            // block any other transaction from working on the same table
            // but with different data
        }
    }

}

是否存在与我上面的示例类似的东西?

解决方法

您可以使用SynchronizedList对象,它会阻止和同步列表上的任何操作,甚至是读取操作,因此最好在添加或更新列表时使用,或者会创建一个CopyOnWriteList永远是一个包含新对象的新列表,并且不会对正在运行的读取操作造成问题。 但是如果你的问题出在列表中某个位置内的对象本身,我建议在你想要阻塞的方法上使用 ReentrantReadWriteLock 策略,这样你可以在锁定时更好地管理,只有当人们更新对象或其他东西时,甚至使用 StampedLock

Here 你可以看到如何使用 Java 锁。您所说的“锁定事务正在使用的数据”非常含糊,您不能阻止整个对象 AFAIK,您可以阻止该对象的一部分,一次只能通过一个线程。无论如何,如果您不想在类方法上使用锁,您可以创建第二个列表,一个已使用的对象 ID 列表,并且不能被其他事务获取,您可以将其与 {{ 3}},或者一个简单的代码,将需要该对象的事务添加到队列中;

List<Object> objects = new ArrayList<>();
List<Integer> objectIds = new ArrayList<>();
Queue<Integer> transactionIds = new PriorityQueue<>();
// code ...
// suppose this is a transaction that run on a thread,and can access our lists
public void doUpdateOnObject() {
    Object object = objects.get(1);
    if (objectsIds.indexOf(object) > 0) {
        transactionIds.add(this.id) // this transactionId
        while(transactionIds.peek() != this.id) { // if you aren't the next,wait    
            Thread.sleep(400);
        }
    }
    objectIds.add(object.getId());
    // here change object fields or whatever;
    objectIds.remove(object.getId());
}

实际上,您的示例工作正常,因为它使用您要锁定的对象作为监视器,因此当一个线程位于同步块内时,其他线程无法访问它。

,

在我对这个问题进行了大量推理之后,@Kaneda 和@user207421 提出了一个解决方案:

public class Table {

    // suppose this is the data of the table and it has a lot of values
    private LinkedList<String> data = new LinkedList();

    public void doTransactionJob() {

        // here we get the data from the list
        // and we ask for monitor on this data so that no other
        // transaction can operate on it
        synchronized(data.get(randomIndex)) {
            // here the transaction works on the data but doesnt
            // block any other transaction from working on the same table
            // but with different data
        }
    }

}

这是因为@Kaneda 写的评论说明了这一点

它返回对象引用的值,如果对 DS 的 get 操作只给出值,您将永远无法更新列表中的对象状态,需要在该位置设置新的对象值再次。

因此,似乎从列表中获取值并在其上请求监视器完全正常。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。