как безопасно увеличивать при использовании потоков в java

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

protected synchronized boolean isOpen()
{
    //this code just calls mymethod intrested where the problem lies

  lock.interested();
    while(!lock.isReady())
    {
    }
    return true;// this statement releases all my threads

 }



public synchronized void  interested()
{

    count++;// how do i make this increment correctly with threads
    System.out.println(count+"-"+ lanes+"-"+ThreadID.get());
    if(count==lanes)
    {

        count =0;
        ready =true;
    }

}

person jambuls    schedule 10.08.2014    source источник
comment
Вам разрешено использовать AtomicInteger? docs.oracle.com/javase/ 7/docs/api/java/util/concurrent/atomic/   -  person Jeanne Boyarsky    schedule 10.08.2014
comment
На самом деле я стараюсь воздерживаться от использования предварительно запрограммированных вещей, другими словами, если я кодирую это как пещерный человек, я точно понимаю, как это работает с нуля.   -  person jambuls    schedule 10.08.2014
comment
возможный дубликат Java Concurrency Incrementing a Value   -  person DavidPostill    schedule 10.08.2014
comment
@jambuls, если вы хотите реализовать это самостоятельно (т. е. заново изобрести колесо), используйте AtomicInteger, как предложила Жанна выше.   -  person Nir Alfasi    schedule 10.08.2014
comment
ОК, поэтому я заменил переменную count атомарным целым числом, это все еще не кажется уличающим. я использую метод incrementAndGet()   -  person jambuls    schedule 10.08.2014
comment
каждый поток в конечном итоге создал свой собственный экземпляр класса, в котором было мое атомарное целое число, поэтому он давал неверный ввод, спасибо за помощь   -  person jambuls    schedule 10.08.2014


Ответы (3)


Проблема с вашим подходом заключается в том, что только один поток может ввести метод synchronized за раз, и, следовательно, вы никогда не продолжите, поскольку все потоки, кроме первых, ожидают ввода метода synchronized, в то время как первый поток выполняет цикл ожидания . Вы должны использовать wait, который не только решит трату циклов ЦП на ваше занятое ожидание, но также освободит связанную блокировку кода synchronized, чтобы следующий поток мог продолжить:

protected synchronized boolean isOpen()
{
    lock.interested();
    while(!lock.isReady())
    {
        wait(); // now the next thread can enter isOpen()
    }
    notify(); // releases the previous thread wait()ing in this method
    return true;
 }

Однако обратите внимание, что это работает довольно ненадежно из-за того, что ваш код разделен на несколько разных объектов. Настоятельно рекомендуется помещать код, поддерживающий счетчик, и код, реализующий ожидание счетчика, в один объект, чтобы работать под одной и той же блокировкой. Структура вашего кода должна гарантировать, что interested() нельзя будет вызвать в экземпляре lock, если isOpen этого не заметит. Из двух фрагментов кода, которые вы разместили, невозможно сделать вывод, так ли это.

person Holger    schedule 11.08.2014

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

Хорошим решением будет использование CountDownLatch.

Из руководства:

CountDownLatch инициализируется заданным счетчиком. Методы await блокируются до тех пор, пока текущий счетчик не достигнет нуля из-за вызовов метода countDown(), после чего все ожидающие потоки освобождаются, а любые последующие вызовы await возвращаются немедленно. Это одноразовое явление — счетчик не может быть сброшен. Если вам нужна версия, которая сбрасывает счетчик, рассмотрите возможность использования CyclicBarrier.

Хороший пример кода можно найти здесь

person Nir Alfasi    schedule 10.08.2014

You should not use synchronised. Because only one thread will acquire monitor at a time.

Вы можете использовать CountDownLatch. Просто определите количество потоков при инициализации CountDownLatch.

private CountDownLatch countDownLatch = new CountDownLatch(no_of_threads);
protected  boolean isOpen()
{
    //this code just calls mymethod intrested where the problem lies

    countDownLatch.countDown();
    countDownLatch.await();
    return true;// this statement releases all my threads
 }


  All the threads are waiting in countDownLatch.await(). Once the required amount of thread comes(countDownLatch.countDown() is called) it will allow to proceed. 
person Siva Kumar    schedule 14.08.2014