Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过java锁定数组中的每个项_Java_Locking_Synchronized_Unlock - Fatal编程技术网

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

通过java锁定数组中的每个项,java,locking,synchronized,unlock,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 f

假设我们有这些类:

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

Ahmad

这种同步是使用带有某种锁的
wait()/notify()
方法实现的。阅读关于它们的Java教程(以及其他同步概念)。

理想情况下,您需要熟悉Java并发包的ReadWriteLock
setValueId
应获得写锁并将其保持到事务提交
getValueId
只需要一个读锁,该读锁可以被其他读锁共享,并在方法结束时释放

还要考虑一些超时,以便锁不会无限期地保持

研究:

  • 读/写锁定模式
  • 数据库系统中的隔离级别
  • 交易处理

    • 您不能使用同步块来实现它,而是需要使用锁之类的东西

      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();
          }
      }
      
      public Main{
      公共静态void main(字符串[]args){
      最终事务T=新事务();
      对于(int n=0;n<10;n++){
      新线程(newrunnable()){
      公开募捐{
      对于(int i=0;i<1000;i++){
      T.setValueByID(i%100,i);
      T.getValueByID(i%100);
      如果(i%20==0)T.commit();
      }
      }  
      }).start();
      }
      }
      }
      类表{
      静态最终记录[]表=新记录[100];
      静态最终ReentrantLock[]锁=新的ReentrantLock[table.length];
      静止的{
      对于(int i=0;i

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

      我想问您另外一个问题……如何从事务类调用多线程?因为您没有编写“类事务扩展线程{}”对于所有这些问题,很抱歉……但我确实是线程初学者……如果可以给我一个简单的例子,说明如何创建单独的线程并从中调用事务方法……再次感谢您的帮助。@user1361554请检查编辑,它现在包含一个main()。如果我想让另一个线程读取第一条记录…我如何返回到该线程并使其运行调用commit()来释放lock@user1361554您可以随时从给定线程使用对T的引用调用commit。
      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();
          }
      }