java - 通过java锁定数组中的每个项目

标签 java locking synchronized unlock

假设我们有这些类:

public  class Record {
    int key;
    int value;
    Record(){
        this.key=0;
        this.value=0;
    }
    Record(int key,int value){
        this.key=key;
        this.value=value;
    }
    public  class Table {
        static final Record[] table = new Record [100];
        static final Object[] locks = new Object[table.length];
        static{
        for(int i = 0; i < table.length; i++) {
            locks[i] = new Object();
        }


        table[0]=new Record(0,0);
        table[1]=new Record(1,10); 
        table[2]=new Record(2,20);
        table[3]=new Record(3,30);
    }
}

我想在 TRAnsaction 类中实现这些方法

void setValueByID(int key, int value)

在 setValueByID 方法完成之前,键值对(记录)被锁定(不能从其他事务读取/写入)。

int getValueByID(int key)

键值对(记录)被锁定,直到事务提交

void commit()

它会解锁当前交易中锁定的所有键值对(记录)

所以,我的实现是:

class Transaction extends Thread {
//there is no problem here  
    public void setValueByID(int key, int value){

    synchronized(Table.locks[key]) {
     Table.table[key].key=key;

    }   
    }
    //the problem is here...
    //how can i make other thread wait until current thread calls Commit()
    public int getValueByID(int key){
            int value=0; 
            synchronized(Table.locks[key]){
            value= Table.table[key].key;
     }
     return value;
} 


void commit(){
}

艾哈迈德

最佳答案

你不能使用同步块(synchronized block)来实现它,相反你需要使用类似锁的东西。

public Main {
    public static void main(String[] args) {
        final Transaction T = new Transaction();
        for (int n = 0; n < 10; n++) {
            new Thread(new Runnable() {
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        T.setValueByID(i % 100, i);
                        T.getValueByID(i % 100);
                        if (i % 20 == 0) T.commit();
                    }
                }  
            }).start();
        }
    }
}
class Table {
    static final Record[] table = new Record[100];
    static final ReentrantLock[] locks = new ReentrantLock[table.length];

    static {
        for (int i = 0; i < table.length; i++) {
            locks[i] = new ReentrantLock();
        }

        table[0] = new Record(0, 0);
        table[1] = new Record(1, 10);
        table[2] = new Record(2, 20);
        table[3] = new Record(3, 30);
    }
}
class Transaction {

    private ThreadLocal<Set<ReentrantLock>> locks = new ThreadLocal<Set<ReentrantLock>>() {
        @Override
        protected Set<ReentrantLock> initialValue() {
            return new HashSet<ReentrantLock>();
        }
    };

    private void attainLock(int key) {
        final ReentrantLock lock = Table.locks[key];
        lock.lock();
        locks.get().add(lock);
    }

    private void releaseLock(int key) {
        final ReentrantLock lock = Table.locks[key];
        releaseLock(lock);
    }

    private void releaseLock(ReentrantLock lock) {
        final Set<ReentrantLock> lockSet = locks.get();
        if (!lockSet.contains(lock)) {
            throw new IllegalStateException("");
        }
        lockSet.remove(lock);
        lock.unlock();
    }

    private void releaseLocks() {
        final Set<ReentrantLock> lockSet = new HashSet<ReentrantLock>(locks.get());
        for (ReentrantLock reentrantLock : lockSet) {
            releaseLock(reentrantLock);
        }
    }

    public void setValueByID(int key, int value) {
        attainLock(key);
        Table.table[key].key = key;
        releaseLock(key);
    }

    public int getValueByID(int key) {
        attainLock(key);
        return Table.table[key].key;
    }

    void commit() {
        releaseLocks();
    }
}

锁的问题在于,在您的交易过程中,如果您在获得锁时不遵循命令,您可能会陷入死锁!此外,您需要确保正确处理异常并始终通过调用 commit() 释放锁。

关于java - 通过java锁定数组中的每个项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10360472/

相关文章:

java - 什么时候应该将方法声明为同步?

java - 设置系统语言

multithreading - 锁定和解锁互斥体的效率如何?互斥体的成本是多少?

java - 锁定同步方法时访问类的非同步方法

java - 设计模式 : How to create synchronized method or block in Singleton pattern in Java?

java - Hibernate多态性

java - 使用 OAuth2ClientAuthenticationProcessingFilter 通过 Spring Boot 登录 Google Oauth2

c - 在 Linux 上如何从作为 cron 作业启动的程序中锁定文件?

java - 彼得森算法逻辑有问题吗?

powershell - Sync'd Hashtable 不是 PowerShell 显示友好的。尝试:[HashTable]::Synchronized(@{})