2015-10-05 15 views
-1

我的目标是让许多线程访问静态属性“nbPlace”,并将其递减。我使用一个变量“互斥体”来让一个线程每次都递减,但是出错了。这里是我的代码:使用信号屏蔽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

什么安迪·特纳在评论中说的是正确的使用倒计时锁存器

我不同意接受的答案,因为如果try 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(); 
     } 
    } 
} 

我从来没有使用过信号量,所以我不能对它们说话。