2012-04-28 2 views
3

Предположим, у нас есть эти классы:блокировки каждого элемента в массиве с помощью Java

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

И я хочу реализовать в классе Сделке этих методов

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

Ahmad

ответ

2

Вы не можете использовать синхронизированные блоки для достижения этого, вместо этого вам нужно будет использовать что-то вроде замков.

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().

+0

Большое спасибо ..... Вы не знаете, сколько вы мне помогли –

+0

Просто я хочу задать вам дополнительный вопрос ... как я могу назвать многопоточность из класса Transaction? потому что вы не писали «класс Transaction extend Thread» {} –

+0

извините за все эти вопросы ... но я действительно начинаю в потоковом ... если можно дать мне простой пример о том, как я могу создать отдельный поток и вызывают методы транзакции из него ... снова спасибо вам за помощь. –

0

Такая синхронизация достигается с использованием методов wait()/notify() с каким-то замком. Прочтите учебник по Java (и другие концепции синхронизации) here.

0

В идеале вам нужно познакомиться с ReadWriteLock из параллельного пакета Java. setValueId должен получить блокировку записи и удерживать ее до завершения транзакции. getValueId требуется только блокировка чтения, которую могут совместно использовать другие блокировки чтения и освобождаться при завершении метода.

Также учитывайте некоторый тайм-аут, чтобы замки не удерживались на неопределенный срок.

Исследования для:/записи шаблона блокировки

  • чтения
  • уровни изоляции в системах баз данных
  • транзакция обработки