Это хороший дизайн для реализации Java синхронизированного ключевого слова в качестве объекта?

Просто для практики я хотел реализовать синхронизированное ключевое слово java как объект java. Вы сказали бы, что код ниже - хороший дизайн для этого? Я думаю, AtomicReference будет иметь аналогичную производительность для AtomicBoolean?

Обновлен код после предложений:

public class SynchronizedBlock implements Runnable{

private final Lock lock;
private final Runnable runnable;

public SynchronizedBlock(Runnable r, Lock l){
    runnable = r;
    lock = l;
}

public void run() {
    try {
        while(!lock.compareAndSet(false, true)){
            Thread.sleep(100);
        }
        runnable.run();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }


}

 }

 public class Lock {
private final AtomicReference<Boolean> locked = new AtomicReference<Boolean>(false);

public boolean compareAndSet(boolean expected, boolean update){
    return locked.compareAndSet(expected, update);
}

public boolean isLocked(){
    return locked.get();
}

public void unlock(){
    locked.set(false);
}
 }

@Test
public void test() {



    final SynchronizedBlock sb = new SynchronizedBlock(new Runnable(){

        public void run() {
            x++;
            System.out.println(x);
        }

    }, new Lock());

    Runnable r1 = new Runnable(){

        int c = 0;
        public void run() {
            while(c<10){
                sb.run();
                c++;
            }
        }

    };

    Runnable r2 = new Runnable(){

        int c = 0;
        public void run() {
            while(c<10){
                sb.run();
                c++;
            }
        }

    };

    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);

    t1.start();
    t2.start();

    while (t1.isAlive() && t2.isAlive()){

    }

    assertEquals(20,x);

}

2 ответа

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

Я бы удалил метод блокировки и поместил разблокировку в блокировку finally, чтобы исключение / ошибка не приводили к блокировке, которая никогда не разблокируется.

Также я бы использовал AtomicBoolean, который является более естественным, чем AtomicReference

Во-первых и самое главное, вы должны удалить Thread.sleep(100), Это приведет к задержке не менее 100 мс даже в конфликте только с двумя потоками.

Вы можете просто использовать AtomicBoolean вместо AtomicReference упростить ваш код. Также, если вы действительно обеспокоены параллелизмом в ситуации высокой конкуренции, вы можете изменить свой код, чтобы проверить, не заблокирован ли он перед выполнением CAS.

while (true) {
  if (lock.isLocked()) continue; // or get() == true if you use AtomicBoolean
  if (lock.compareAndSet(false, true)) 
    break;
}

Это пример блокировки TTAS(Test-Test-And-Set), которая использует преимущества локального вращения для уменьшения доступа к основной памяти во время цикла. Смотрите http://en.wikipedia.org/wiki/Test_and_Test-and-set

Другие вопросы по тегам