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

voase2hg  于 2021-07-12  发布在  Java
关注(0)|答案(1)|浏览(350)

最近,在研究现代数据库中的事务时,我发现现在的事务并不在整个集合或表上使用锁或监视器,而是在将由事务执行的不同操作使用的集合或表的数据上使用锁或监视器。
所以我在想,假设我们有一个数据结构,它可以是一个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
        }
    }

}

是否存在类似于我上面例子的东西?

vcirk6k6

vcirk6k61#

你可以使用 SynchronizedList 对象,它将阻止和同步列表上的任何操作,甚至读取操作,因此在添加或更新列表或 CopyOnWriteList 这将创建一个包含新对象的新列表,并且不会对正在运行的读取操作造成问题。但是如果您的问题是对象本身位于列表中的某个位置,我建议使用 ReentrantReadWriteLock 策略上的方法,所以你可以更好地管理锁定时,只有当人们更新对象或某事,甚至使用 StampedLock .
在这里您可以看到如何使用java锁。你说的“锁定事务正在使用的数据”是非常模糊的,你不能完全阻塞一个对象,你可以阻塞该对象的一部分,一次只能有一个线程通过。无论如何,如果您不想在类方法上使用锁,您可以创建第二个列表,一个已使用的对象id的列表,并且其他事务无法获得该列表,您可以将其与lamport bakery算法或简单的代码相结合,将需要该对象的事务添加到队列中;

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());
}

实际上,您的示例运行得很好,因为它使用您要锁定的对象作为监视器,所以当一个线程在同步块中时,没有其他线程可以访问它。

相关问题