То, как действительно определяют, заблокирован ли объект (синхронизировалось) так для не блокирования в Java?

Каждый раз, когда я должен передать в наборе объектов к функции, если я хочу, чтобы функция не изменилась, значения передали в - я использую кортежи.

Еще, если я хочу иметь функцию для изменения значений, я использую список.

Всегда, если Вы пользуетесь внешними библиотеками и потребностью передать в списке значений к функции и не уверены в целостности данных, используйте кортеж.

71
задан Ben S 22 November 2009 в 20:15
поделиться

3 ответа

One thing to note is that the instant you receive such information, it's stale. In other words, you could be told that no-one has the lock, but then when you try to acquire it, you block because another thread took out the lock between the check and you trying to acquire it.

Brian is right to point at Lock, but I think what you really want is its tryLock method:

Lock lock = new ReentrantLock();
......
if (lock.tryLock())
{
    // Got the lock
    try
    {
        // Process record
    }
    finally
    {
        // Make sure to unlock so that we don't cause a deadlock
        lock.unlock();
    }
}
else
{
    // Someone else had the lock, abort
}

You can also call tryLock with an amount of time to wait - so you could try to acquire it for a tenth of a second, then abort if you can't get it (for example).

(I think it's a pity that the Java API doesn't - as far as I'm aware - provide the same functionality for the "built-in" locking, as the Monitor class does in .NET. Then again, there are plenty of other things I dislike in both platforms when it comes to threading - every object potentially having a monitor, for example!)

77
ответ дан 24 November 2019 в 13:04
поделиться

Take a look at the Lock objects introduced in the Java 5 concurrency packages.

e.g.

Lock lock = new ReentrantLock()
if (lock.tryLock()) {
   try {
      // do stuff using the lock...
   }
   finally {
      lock.unlock();
   }
}
   ...

The ReentrantLock object is essentially doing the same thing as the traditional synchronized mechanism, but with more functionality.

EDIT: As Jon has noted, the isLocked() method tells you at that instant, and thereafter that information is out of date. The tryLock() method will give more reliable operation (note you can use this with a timeout as well)

EDIT #2: Example now includes tryLock()/unlock() for clarity.

23
ответ дан 24 November 2019 в 13:04
поделиться

Хотя ответы Lock очень хороши, я подумал, что опубликую альтернативу с другой структурой данных. По сути, ваши различные потоки хотят знать, какие записи заблокированы, а какие нет. Один из способов сделать это - отслеживать заблокированные записи и удостовериться, что структура данных имеет правильные атомарные операции для добавления записей в заблокированный набор.

Я буду использовать CopyOnWriteArrayList в качестве примера, потому что он менее "волшебный" для иллюстрации . CopyOnWriteArraySet - более подходящая структура. Если у вас в среднем заблокировано много-много записей одновременно, эти реализации могут сказаться на производительности. Правильно синхронизированный HashSet тоже будет работать, а блокировки будут короткими.

В основном код использования будет выглядеть так:

CopyOnWriteArrayList<Record> lockedRecords = ....
...
if (!lockedRecords.addIfAbsent(record))
    return; // didn't get the lock, record is already locked

try {
    // Do the record stuff
}        
finally {
    lockedRecords.remove(record);
}

Он избавляет вас от необходимости управлять блокировкой для каждой записи и предоставляет единое место, если по какой-либо причине потребуется снятие всех блокировок. С другой стороны, если у вас когда-либо будет больше, чем несколько записей, то настоящий HashSet с синхронизацией может работать лучше, поскольку поиск по добавлению / удалению будет O (1) вместо линейного.

Просто другой способ глядя на вещи. Просто зависит от ваших фактических требований к потокам. Лично я бы использовал Collections.synchronizedSet (new HashSet ()), потому что он будет очень быстрым ... единственное значение состоит в том, что потоки могут уступить, хотя в противном случае они бы этого не сделали.

если у вас когда-либо будет больше, чем несколько записей, то настоящий HashSet с синхронизацией может оказаться лучше, поскольку поиск по добавлению / удалению будет O (1) вместо линейного.

Просто другой взгляд на вещи. Просто зависит от ваших фактических требований к потокам. Лично я бы использовал Collections.synchronizedSet (new HashSet ()), потому что он будет очень быстрым ... единственное значение состоит в том, что потоки могут уступить, хотя в противном случае они бы этого не сделали.

если у вас когда-либо будет больше, чем несколько записей, то настоящий HashSet с синхронизацией может оказаться лучше, поскольку поиск по добавлению / удалению будет O (1) вместо линейного.

Просто другой взгляд на вещи. Просто зависит от ваших фактических требований к потокам. Лично я бы использовал Collections.synchronizedSet (new HashSet ()), потому что он будет очень быстрым ... единственное значение состоит в том, что потоки могут уступить, хотя в противном случае они бы этого не сделали.

3
ответ дан 24 November 2019 в 13:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: