2016-11-06 2 views
1

Я ищу рекомендацию о том, как сделать этот код потокобезопасным с блокировками на Java. Я знаю, что есть много исправлений с замками; непонятные проблемы, расовые условия и т. д., которые могут появиться. Вот основная идея о том, что я пытаюсь достичь, реализуемый довольно наивным:Использование Java Queued Locks

public class MultipleThreadWriter { 

boolean isUpgrading=false; 
boolean isWriting=false; 


public void writeData(String uniqueId) { 

    if (isUpgrading) 
     //block until isUpgrading is false 

    isWriting = true; 
    { 
     //do write stuff  
    } 
    isWriting = false; 

} 

public void upgradeSystem() { 

    if (isWriting) 
     //block until isWriting is false 

    isUpgrading = true; 
    { 
     //do updates 
    } 
    isUpgrading = false; 

} 

} 

Основная идея заключается в том, что несколько потоков разрешено записывать данные одновременно. Это не имеет значения, так как никакие два потока никогда не будут записывать данные, относящиеся к одному и тому же уникальному. Тем не менее, «обновление системы» управляет данными для всех уникальных идентификаторов, поэтому оно должно блокировать (ждать в строке), пока не будут записаны данные до того, как они начнутся, и в этот момент он блокирует все записи до тех пор, пока они не будут завершены. (Это определенно не шаблон потребления/производителя, происходящий здесь - обновление происходит произвольно, то есть не имеет никакого отношения к записываемым данным.)

ответ

0

Основываясь на ответе от @DaoWen, это мое непроверенное решение.

public class MultipleThreadWriter { 

private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 
private final Lock r = rwl.readLock(); 
private final Lock w = rwl.writeLock(); 


public void writeData() { 

    r.lock(); 
    try { 
     //do write stuff  
    } finally { 
     r.unlock(); 
    } 

} 

public void upgradeSystem() { 

    w.lock(); 
    try { 
     //do updates 
    } finally { 
     w.unlock(); 
    } 

} 
} 
2

Это звучит неплохо для приложения readers-writer lock.

Однако в этом случае ваши «читатели» - это небольшие задачи обновления, которые могут выполняться одновременно, а ваш «писатель» - это задача обновления системы.

Там же реализация этого в стандартной библиотеке Java:

java.util.concurrent.locks.ReentrantReadWriteLock

Замок имеет справедливую и не БАЛ режимов. Если вы хотите, чтобы обновление системы выполнялось как можно скорее после его запланированного использования, используйте режим fair блокировки. Если вы хотите, чтобы обновление было применено во время простоя (т. Е. Дождитесь, пока не произойдет никаких небольших обновлений), вы можете использовать non-fair.

Поскольку это немного неортодоксальное приложение блокировки чтения-записи (ваши читатели на самом деле тоже пишут!), Обязательно прокомментируйте это в своем коде. Вы даже можете подумать о создании обертки вокруг класса ReentrantReadWriteLock, который предоставляет методы localUpdateLock против globalUpdateLock, которые делегируют readLock и writeLock соответственно.

+0

Спасибо. Основываясь на вашей идее, я создал это решение: 'public class MultipleThreadWriter { private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); закрытый конечный замок r = rwl.readLock(); закрытый финал Lock w = rwl.writeLock(); \t \t \t общественный недействительный WriteData() { \t \t \t r.lock(); \t \t попробовать {\t \t \t \t // делать записи вещи \t \t \t} наконец { \t \t \t р.разблокировать(); \t \t} \t \t \t \t } \t \t общественного недействительными upgradeSystem() { \t \t \t \t w.lock(); \t \t попробовать { \t \t \t // делать обновления \t \t} наконец { \t \t \t w.unlock(); \t \t} \t} } ' – bitsmcgee77

+0

К сожалению о неразборчивом коде в комментариях! Не могу понять, насколько я должен правильно отформатировать его. – bitsmcgee77