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

如何在java中请求数据结构的数据锁定,java,data-structures,concurrency,synchronization,Java,Data Structures,Concurrency,Synchronization,最近,在研究现代数据库中的事务时,我发现现在的事务不在整个集合或表上使用锁或监视器,但它们通常在集合或表的数据上使用锁或监视器,这些数据将由事务执行的不同操作使用 所以我在想,假设我们有一个数据结构,它可以是一个LinkedList,一个Hashtable等等,多个不同的事务想要同时访问这个结构来更新数据。如何请求锁定事务将要使用的数据,而不是整个对象数据结构?这将明显提高性能,因为使用相同数据结构的不同数据的不同更新事务将同时发生 我将尝试进一步阐明我想要实现的目标,以下是一个示例: publ

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

所以我在想,假设我们有一个数据结构,它可以是一个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
        }
    }

}
公共类表{
//假设这是表的数据,它有很多值
私有LinkedList数据=新LinkedList();
public void doTransactionJob(){
//这里我们从列表中获取数据
//我们要求监控这些数据,这样就不会有其他
//事务可以对其进行操作
已同步(data.get(randomIndex)){
//在这里,事务对数据起作用,但不起作用
//阻止任何其他事务处理同一个表
//但数据不同
}
}
}

是否存在与我上面的示例类似的内容?

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

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

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());
}
List objects=new ArrayList();
List objectid=new ArrayList();
Queue TransactionId=new PriorityQueue();
//代码。。。
//假设这是一个在线程上运行的事务,可以访问我们的列表
public void doUpdateOnObject(){
Object=objects.get(1);
if(objectsIds.indexOf(object)>0){
transactionId.add(this.id)//this transactionId
while(transactionIds.peek()!=this.id){//如果您不是下一个,请稍候
睡眠(400);
}
}
add(object.getId());
//这里更改对象字段或其他内容;
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
        }
    }

}
公共类表{
//假设这是表的数据,它有很多值
private LinkedList data=newlinkedList();
public void doTransactionJob(){
//这里我们从列表中获取数据
//我们要求监控这些数据,这样就不会有其他
//事务可以对其进行操作
已同步(data.get(randomIndex)){
//在这里,事务对数据起作用,但不起作用
//阻止任何其他事务处理同一个表
//但数据不同
}
}
}
这是因为@Kaneda写了一条评论


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


因此,显然从列表中获取值并要求对其进行监视是完全正常的。

我不知道是不是我,但您说事务锁定集合上的数据,而不是集合本身,然后在您提出的如何锁定集合上的数据的问题上,不是集合本身…@Kaneda我可能没有写,我的意思是事务要求锁定数据而不是整个集合,我想实现的是如何锁定数据而不是整个集合(很抱歉,我不是英语母语人士)。类似的情况确实存在。当你尝试它时发生了什么?@user207421我没有尝试,因为一开始我不知道它可能是一个解决方案,我仍然不明白它是如何工作的,当我执行get操作时,我java返回值,而不是引用,正因为如此,我不应该能够获取存储在数据结构中的真实对象的锁,对吗?它返回对象引用的值,如果DS上的get操作只给出值,您将永远无法更新列表中的对象状态,需要再次将新对象值设置在该位置。SynchronizedList似乎锁定了整个集合,对吗?我只想锁定事务正在使用的数据,ReentrantLock是否可以做到这一点?我用一个清晰的示例和策略更新了我的答案