2015-10-05 2 views
-1

Моя цель - получить доступ к потокам в статическом атрибуте «nbPlace» ONE AT TIME и уменьшить его. Я использую переменную «mutex», чтобы каждый поток уменьшался каждый раз, однако что-то пошло не так. Вот мой код:блокировка потоков в java с помощью семафора

public class Client extends Thread{ 

static int nbPlace=10; 
static int mutex=1; 

public Client(String name){ 
    super(name); 
} 
public void run(){ 
    if (mutex==1) { 
     mutex=0; 
     decrementer(getName()); 
     mutex=1; 
    } else 
     try { 
      join(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

} 
static void decrementer(String nomThread){ 
    nbPlace--; System.out.println("dec par "+nomThread+" ... nbplace="+nbPlace); 
} 
public static void main(String[] args) { 
    // TODO Auto-generated method stub 
Client [] t= new Client[5]; 
for(int i=0;i<5;i++) t[i]=new Client ("thread n° "+i); 
for (int i=0;i<5;i++) t[i].start(); 

} 

}

+0

Почему бы не просто сделать метод 'декрементер'' синхронизированным'? –

+1

«Что-то пошло не так», можете ли вы уточнить? –

+1

Есть ли веская причина не использовать AtomicInteger или CountdownLatch? Или Семафор, если на то пошло. –

ответ

0

Java уже есть семафор реализации, просто использовать его:

public class Client extends Thread{ 

    static int nbPlace=10; 
    private final Semaphore sem = new Semaphore(1); 

    public Client(String name){ 
     super(name); 
    } 
    public void run(){ 
     try { 
      sem.acquire(); 
      decrementer(getName()); 
      sem.release(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
    static void decrementer(String nomThread){ 
     nbPlace--; System.out.println("dec par "+nomThread+" ... nbplace="+nbPlace); 
    } 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
    Client [] t= new Client[5]; 
    for(int i=0;i<5;i++) t[i]=new Client ("thread n° "+i); 
    for (int i=0;i<5;i++) t[i].start(); 
    } 
} 
0

Если поток попадает в состояние if (mutex==1) {, когда другой поток в этом блоке, он переходит к else и вызывает join().

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

+0

спасибо, это объясняет, что на самом деле происходит :) – ghassen92

0

Нет, все так не работает на Java. Вы не можете одновременно обращаться к изменяемым данным без надлежащей синхронизации.

Самый простой способ сделать этот код протектора сейф:

static int nbPlace = 10; 
static final Object object = new Object(); 

public Client(String name) { 
    super(name); 
} 

public void run() { 
    synchronized (object) { 
     decrementer(getName()); 
    } 
} 
1

Что Энди Тернер сказал в комментариях, правильное использование обратный отсчет защелка.

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

public synchronized void myMethod(){ 
    //anything here is only able to be run by one thread at a time 
} 

Другая форма синхронизируются является

public class MyClass { 
final Object lock = new Object(); 
public void myMethod(){ 
    synchronized(lock){ 
     //anything here is only able to be run by one thread at a time 
    } 
} 

вы можете также использовать возвратные блокировки

import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

public class MyClass{ 
    final Lock lock = new ReentrantLock(); 
    public void myMethod(){ 
     lock.lock(); 
     try{ 
      //anything here is only able to be run by one thread at a time 
     }finally{ 
      lock.unlock(); 
     } 
    } 
} 

Тогда есть ReadWriteLock, что позволяет неограниченное количество потоков для чтения до тех пор, как нить не имеет блокировки для записи

import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReadWriteLock; 
import java.util.concurrent.locks.ReentrantReadWriteLock; 

public class MyClass { 
    final ReadWriteLock rwlock = new ReentrantReadWriteLock(); 
    public void myReadMethod(){ 
     Lock lock = rwlock.readLock(); 
     lock.lock(); 
     try{ 
      //anything here is only able to be run 
      //by any thread that is reading as long 
      //as another thread doesn't have the write lock 
     }finally{ 
      lock.unlock(); 
     } 
    } 

    public void myWriteMethod(){ 
     Lock lock = rwlock.writeLock(); 
     lock.lock(); 
     try{ 
      //anything here is only able to be run by one thread at a time 
     }finally{ 
      lock.unlock(); 
     } 
    } 
} 

Я никогда не пользовался Семафорами, поэтому я не могу говорить на них.

Смежные вопросы